Index: base/applications/network/ipconfig/CMakeLists.txt =================================================================== --- base/applications/network/ipconfig/CMakeLists.txt (revision 73120) +++ base/applications/network/ipconfig/CMakeLists.txt (working copy) @@ -1,5 +1,5 @@ add_executable(ipconfig ipconfig.c ipconfig.rc) set_module_type(ipconfig win32cui) -add_importlibs(ipconfig user32 iphlpapi advapi32 msvcrt kernel32) +add_importlibs(ipconfig user32 iphlpapi dnsapi advapi32 msvcrt kernel32) add_cd_file(TARGET ipconfig DESTINATION reactos/system32 FOR all) Index: base/applications/network/ipconfig/ipconfig.c =================================================================== --- base/applications/network/ipconfig/ipconfig.c (revision 73120) +++ base/applications/network/ipconfig/ipconfig.c (working copy) @@ -21,6 +21,7 @@ #include #include #include +#include #include "resource.h" @@ -799,7 +800,7 @@ else if (DoRenew) Renew(NULL); else if (DoFlushdns) - _tprintf(_T("\nSorry /flushdns is not implemented yet\n")); + DnsFlushResolverCache(); else if (DoRegisterdns) _tprintf(_T("\nSorry /registerdns is not implemented yet\n")); else if (DoDisplaydns) Index: boot/bootdata/hivesft.inf =================================================================== --- boot/bootdata/hivesft.inf (revision 73120) +++ boot/bootdata/hivesft.inf (working copy) @@ -1423,7 +1423,7 @@ ; SvcHost services HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost",,0x00000012 HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost","DcomLaunch",0x00010000,"PlugPlay" -HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost","netsvcs",0x00010000,"DHCP","BITS","lanmanserver","lanmanworkstation","Schedule","winmgmt" +HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost","netsvcs",0x00010000,"DHCP","BITS","lanmanserver","lanmanworkstation","Schedule","winmgmt","DNSCache" ; Win32 config HKLM,"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows",,0x00000012 Index: dll/win32/CMakeLists.txt =================================================================== --- dll/win32/CMakeLists.txt (revision 73123) +++ dll/win32/CMakeLists.txt (working copy) @@ -37,6 +37,7 @@ add_subdirectory(dciman32) add_subdirectory(devmgr) add_subdirectory(dnsapi) +add_subdirectory(dnsrslvr) add_subdirectory(esent) add_subdirectory(faultrep) add_subdirectory(fltlib) Index: dll/win32/dnsapi/CMakeLists.txt =================================================================== --- dll/win32/dnsapi/CMakeLists.txt (revision 73123) +++ dll/win32/dnsapi/CMakeLists.txt (working copy) @@ -2,7 +2,8 @@ include_directories( include ${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/adns/src - ${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/adns/adns_win32) + ${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/adns/adns_win32 + ${REACTOS_SOURCE_DIR}/dll/win32/dnsrslvr) add_definitions(-DADNS_JGAA_WIN32) spec2def(dnsapi.dll dnsapi.spec ADD_IMPORTLIB) @@ -24,6 +25,6 @@ set_module_type(dnsapi win32dll) target_link_libraries(dnsapi adns) -add_importlibs(dnsapi advapi32 user32 ws2_32 iphlpapi msvcrt kernel32 ntdll) +add_importlibs(dnsapi advapi32 user32 ws2_32 iphlpapi dnsrslvr msvcrt kernel32 ntdll) add_pch(dnsapi dnsapi/precomp.h SOURCE) add_cd_file(TARGET dnsapi DESTINATION reactos/system32 FOR all) Index: dll/win32/dnsapi/dnsapi/query.c =================================================================== --- dll/win32/dnsapi/dnsapi/query.c (revision 73123) +++ dll/win32/dnsapi/dnsapi/query.c (working copy) @@ -11,11 +11,27 @@ #include "precomp.h" #include #include +#include #include #define NDEBUG #include +DNS_STATUS WINAPI +GetCurrentTimeInSeconds() +{ + FILETIME Time; + FILETIME Adjustment; + ULARGE_INTEGER lTime,lAdj; + SYSTEMTIME st = { 1970,1,0,1,0,0,0 }; + SystemTimeToFileTime(&st, &Adjustment); + memcpy(&lAdj, &Adjustment, sizeof(lAdj)); + GetSystemTimeAsFileTime(&Time); + memcpy(&lTime, &Time, sizeof(lTime)); + lTime.QuadPart -= lAdj.QuadPart; + return (DWORD)(lTime.QuadPart/10000000LLU); +} + /* DnsQuery **************************** * Begin a DNS query, and allow the result to be placed in the application * supplied result pointer. The result can be manipulated with the record @@ -588,6 +604,8 @@ return Address; } +#define CNAME_LOOP_MAX 16 + DNS_STATUS WINAPI DnsQuery_W(LPCWSTR Name, WORD Type, @@ -597,20 +615,25 @@ PVOID *Reserved) { adns_state astate; - int quflags = (Options & DNS_QUERY_NO_RECURSION) == 0 ? adns_qf_search : 0; + int quflags = 0; int adns_error; adns_answer *answer; LPSTR CurrentName; - unsigned i, CNameLoop; + unsigned i, CNameLoop, NumAliases = 0; PFIXED_INFO network_info; ULONG network_info_blen = 0; - DWORD network_info_result; + DWORD error; PIP_ADDR_STRING pip; IP4_ADDRESS Address; + PDNS_RECORDW DnsRecord; struct in_addr addr; PCHAR HostWithDomainName; PCHAR AnsiName; + PCHAR Aliases[CNAME_LOOP_MAX]; size_t NameLen = 0; + DNS_STATUS Status; + HANDLE DnsClientPipeHandle; + PVOID hHeap; if (Name == NULL) return ERROR_INVALID_PARAMETER; @@ -620,6 +643,7 @@ return ERROR_INVALID_PARAMETER; *QueryResultSet = 0; + hHeap = RtlGetProcessHeap(); switch (Type) { @@ -633,7 +657,7 @@ 0, NULL, 0); - AnsiName = RtlAllocateHeap(RtlGetProcessHeap(), 0, NameLen); + AnsiName = RtlAllocateHeap(hHeap, 0, NameLen); if (NULL == AnsiName) { return ERROR_OUTOFMEMORY; @@ -650,8 +674,8 @@ /* Is it an IPv4 address? */ if (ParseV4Address(AnsiName, &Address)) { - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); + RtlFreeHeap(hHeap, 0, AnsiName); + *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(hHeap, 0, sizeof(DNS_RECORD)); if (NULL == *QueryResultSet) { @@ -674,7 +698,7 @@ if (AnsiName[0] == '-' || AnsiName[0] == '_' || AnsiName[NameLen - 1] == '-' || AnsiName[NameLen - 1] == '_' || strstr(AnsiName, "..") != NULL) { - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); + RtlFreeHeap(hHeap, 0, AnsiName); return ERROR_INVALID_NAME; } i = 0; @@ -685,7 +709,7 @@ (AnsiName[i] >= '0' && AnsiName[i] <= '9') || AnsiName[i] == '-' || AnsiName[i] == '_' || AnsiName[i] == '.')) { - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); + RtlFreeHeap(hHeap, 0, AnsiName); return ERROR_INVALID_NAME; } i++; @@ -695,8 +719,8 @@ { if ((Address = FindEntryInHosts(AnsiName)) != 0) { - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); + RtlFreeHeap(hHeap, 0, AnsiName); + *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(hHeap, 0, sizeof(DNS_RECORD)); if (NULL == *QueryResultSet) { @@ -714,29 +738,62 @@ } } - network_info_result = GetNetworkParams(NULL, &network_info_blen); - network_info = (PFIXED_INFO)RtlAllocateHeap(RtlGetProcessHeap(), 0, (size_t)network_info_blen); + if ((Options & DNS_QUERY_BYPASS_CACHE) == 0) + { + error = DnsCApiInitialize(&DnsClientPipeHandle); + if (error == ERROR_SUCCESS) + { + DPRINT("Connected to DNS Client service %x\n", DnsClientPipeHandle); + if (DnsCApiQueryRecord(DnsClientPipeHandle, Name, (PDNS_RECORDW *)QueryResultSet)) + { + DPRINT("Found entry for %ls in cache %lx\n", Name, (*QueryResultSet)->Data.A.IpAddress); + } + else + { + DPRINT("Entry for %ls not found in cache\n", Name); + } + /* check expiration and remove it if expired */ + if (*QueryResultSet && (*QueryResultSet)->pName && (*QueryResultSet)->dwTtl > GetCurrentTimeInSeconds()) + { + if (!DnsCApiRemoveRecord(DnsClientPipeHandle, Name)) + { + DPRINT("Failed to remove expired entry for %ls from cache\n", Name); + } + DnsIntFreeRecordList(*QueryResultSet); + *QueryResultSet = NULL; + } + DnsCApiCleanup(DnsClientPipeHandle); + if (*QueryResultSet && (*QueryResultSet)->pName) + { + RtlFreeHeap(hHeap, 0, AnsiName); + return ERROR_SUCCESS; + } + } + } + + GetNetworkParams(NULL, &network_info_blen); + network_info = (PFIXED_INFO)RtlAllocateHeap(hHeap, 0, (size_t)network_info_blen); if (NULL == network_info) { return ERROR_OUTOFMEMORY; } - network_info_result = GetNetworkParams(network_info, &network_info_blen); - if (network_info_result != ERROR_SUCCESS) + error = GetNetworkParams(network_info, &network_info_blen); + if (error != ERROR_SUCCESS) { - RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); - return network_info_result; + RtlFreeHeap(hHeap, 0, network_info); + return error; } if ((Address = CheckForCurrentHostname(NameLen != 0 ? AnsiName : network_info->HostName, network_info)) != 0) { size_t TempLen = 2, StringLength = 0; - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); + RtlFreeHeap(hHeap, 0, AnsiName); StringCchLengthA(network_info->HostName, sizeof(network_info->HostName), &StringLength); TempLen += StringLength; StringCchLengthA(network_info->DomainName, sizeof(network_info->DomainName), &StringLength); TempLen += StringLength; - HostWithDomainName = (PCHAR)RtlAllocateHeap(RtlGetProcessHeap(), 0, TempLen); + HostWithDomainName = (PCHAR)RtlAllocateHeap(hHeap, 0, TempLen); StringCchCopyA(HostWithDomainName, TempLen, network_info->HostName); if (network_info->DomainName) { @@ -743,12 +800,12 @@ StringCchCatA(HostWithDomainName, TempLen, "."); StringCchCatA(HostWithDomainName, TempLen, network_info->DomainName); } - RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); - *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); + RtlFreeHeap(hHeap, 0, network_info); + *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(hHeap, 0, sizeof(DNS_RECORD)); if (NULL == *QueryResultSet) { - RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName); + RtlFreeHeap(hHeap, 0, HostWithDomainName); return ERROR_OUTOFMEMORY; } @@ -759,14 +816,14 @@ (*QueryResultSet)->pName = (LPSTR)DnsCToW(HostWithDomainName); - RtlFreeHeap(RtlGetProcessHeap(), 0, HostWithDomainName); + RtlFreeHeap(hHeap, 0, HostWithDomainName); return (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY; } if ((Options & DNS_QUERY_NO_WIRE_QUERY) != 0) { - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); + RtlFreeHeap(hHeap, 0, AnsiName); + RtlFreeHeap(hHeap, 0, network_info); return ERROR_FILE_NOT_FOUND; } @@ -773,8 +830,8 @@ adns_error = adns_init(&astate, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn, 0); if (adns_error != adns_s_ok) { - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); + RtlFreeHeap(hHeap, 0, AnsiName); + RtlFreeHeap(hHeap, 0, network_info); return DnsIntTranslateAdnsToDNS_STATUS(adns_error); } for (pip = &(network_info->DnsServerList); pip; pip = pip->Next) @@ -783,11 +840,14 @@ if ((addr.s_addr != INADDR_ANY) && (addr.s_addr != INADDR_NONE)) adns_addserver(astate, addr); } +#ifdef DNSAPI_SEARCH_DOMAIN if (network_info->DomainName) { adns_ccf_search(astate, "LOCALDOMAIN", -1, network_info->DomainName); + quflags |= adns_qf_search; } - RtlFreeHeap(RtlGetProcessHeap(), 0, network_info); +#endif + RtlFreeHeap(hHeap, 0, network_info); if (Servers) { @@ -810,8 +870,6 @@ * CNAME loops. */ -#define CNAME_LOOP_MAX 16 - CurrentName = AnsiName; for (CNameLoop = 0; CNameLoop < CNAME_LOOP_MAX; CNameLoop++) @@ -820,73 +878,84 @@ if (adns_error != adns_s_ok) { - adns_finish(astate); - - if (CurrentName != AnsiName) - RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); - - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - return DnsIntTranslateAdnsToDNS_STATUS(adns_error); + Status = DnsIntTranslateAdnsToDNS_STATUS(adns_error); + goto exit; } if (answer && answer->rrs.addr) { - if (CurrentName != AnsiName) - RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); + *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(hHeap, 0, sizeof(DNS_RECORD)); - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - *QueryResultSet = (PDNS_RECORD)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(DNS_RECORD)); - if (NULL == *QueryResultSet) { - adns_finish(astate); - return ERROR_OUTOFMEMORY; + Status = ERROR_OUTOFMEMORY; + goto exit; } (*QueryResultSet)->pNext = NULL; (*QueryResultSet)->wType = Type; + (*QueryResultSet)->dwTtl = answer->expires; (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA); (*QueryResultSet)->Data.A.IpAddress = answer->rrs.addr->addr.inet.sin_addr.s_addr; - adns_finish(astate); - + error = DnsCApiInitialize(&DnsClientPipeHandle); + if (error == ERROR_SUCCESS) + { + DPRINT("Connected to DNS Client service %x\n", DnsClientPipeHandle); + for (i = 0; i < NumAliases; i++) + { + DnsRecord = (PDNS_RECORDW)*QueryResultSet; + DnsRecord->pName = DnsCToW(Aliases[i]); + if (!DnsCApiAddRecord(DnsClientPipeHandle, DnsRecord)) + { + DPRINT("Failed to add entry for %ls to cache\n", DnsRecord->pName); + } + RtlFreeHeap(hHeap, 0, Aliases[i]); + RtlFreeHeap(hHeap, 0, DnsRecord->pName); + } + } (*QueryResultSet)->pName = (LPSTR)xstrsave(Name); - - return (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY; + if (error == ERROR_SUCCESS) + { + if (!DnsCApiAddRecord(DnsClientPipeHandle, (PDNS_RECORDW)*QueryResultSet)) + { + DPRINT("Failed to add entry for %ls to cache\n", Name); + } + DnsCApiCleanup(DnsClientPipeHandle); + } + Status = (*QueryResultSet)->pName ? ERROR_SUCCESS : ERROR_OUTOFMEMORY; + goto exit; } - if (NULL == answer || adns_s_prohibitedcname != answer->status || NULL == answer->cname) + if (NULL == answer || adns_s_prohibitedcname != answer->status || NULL == answer->cname || (Options & DNS_QUERY_NO_RECURSION) != 0) { - adns_finish(astate); - - if (CurrentName != AnsiName) - RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); - - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - return ERROR_FILE_NOT_FOUND; + Status = ERROR_FILE_NOT_FOUND; + goto exit; } if (CurrentName != AnsiName) - RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); + { + Aliases[NumAliases++] = CurrentName; + } CurrentName = (LPSTR)xstrsaveA(answer->cname); if (!CurrentName) { - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - adns_finish(astate); - return ERROR_OUTOFMEMORY; + Status = ERROR_OUTOFMEMORY; + goto exit; } } - adns_finish(astate); - RtlFreeHeap(RtlGetProcessHeap(), 0, AnsiName); - RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentName); - return ERROR_FILE_NOT_FOUND; - default: return ERROR_OUTOFMEMORY; /* XXX arty: find a better error code. */ } + +exit: + adns_finish(astate); + if (CurrentName && CurrentName != AnsiName) RtlFreeHeap(hHeap, 0, CurrentName); + if (AnsiName) RtlFreeHeap(hHeap, 0, AnsiName); + return Status; } DNS_STATUS WINAPI @@ -943,3 +1012,19 @@ ToDelete = next; } } + +DNS_STATUS WINAPI +DnsFlushResolverCache() +{ + HANDLE DnsClientPipeHandle; + DWORD error = DnsCApiInitialize(&DnsClientPipeHandle); + if (error != ERROR_SUCCESS) + return ERROR_PIPE_NOT_CONNECTED; + DPRINT("Connected to DNS Client service %x\n", DnsClientPipeHandle); + if (!DnsCApiFlushAllRecords(DnsClientPipeHandle)) + { + DPRINT("DNS cache flushing error\n"); + } + DnsCApiCleanup(DnsClientPipeHandle); + return ERROR_SUCCESS; +} Index: dll/win32/dnsapi/dnsapi/stubs.c =================================================================== --- dll/win32/dnsapi/dnsapi/stubs.c (revision 73123) +++ dll/win32/dnsapi/dnsapi/stubs.c (working copy) @@ -216,13 +216,6 @@ return ERROR_OUTOFMEMORY; } -DNS_STATUS WINAPI -DnsFlushResolverCache() -{ - UNIMPLEMENTED; - return ERROR_OUTOFMEMORY; -} - BOOL WINAPI DnsFlushResolverCacheEntry_A(PCSTR entry) { @@ -813,13 +806,6 @@ } DNS_STATUS WINAPI -GetCurrentTimeInSeconds() -{ - UNIMPLEMENTED; - return ERROR_OUTOFMEMORY; -} - -DNS_STATUS WINAPI DnsNotifyResolver() { UNIMPLEMENTED; Index: dll/win32/dnsrslvr/CMakeLists.txt =================================================================== --- dll/win32/dnsrslvr/CMakeLists.txt (revision 0) +++ dll/win32/dnsrslvr/CMakeLists.txt (working copy) @@ -0,0 +1,17 @@ +spec2def(dnsrslvr.dll dnsrslvr.spec ADD_IMPORTLIB) + +list(APPEND SOURCE + cache.c + pipe.c + service.c + precomp.h) + +add_library(dnsrslvr SHARED + ${SOURCE} + dnsrslvr.rc + ${CMAKE_CURRENT_BINARY_DIR}/dnsrslvr.def) + +set_module_type(dnsrslvr win32dll) +add_importlibs(dnsrslvr advapi32 dnsapi msvcrt kernel32 ntdll) +add_pch(dnsrslvr precomp.h SOURCE) +add_cd_file(TARGET dnsrslvr DESTINATION reactos/system32 FOR all) Index: dll/win32/dnsrslvr/cache.c =================================================================== --- dll/win32/dnsrslvr/cache.c (revision 0) +++ dll/win32/dnsrslvr/cache.c (working copy) @@ -0,0 +1,185 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/cache.c + * PURPOSE: DNSAPI cache functions. + * PROGRAMER: Peter Hater + */ + +#include "precomp.h" +#include + +#define NDEBUG +#include + +static TCACHE DnsCache; +static BOOL DnsCacheInitialized = FALSE; + +#define DnsCacheLock() EnterCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock); +#define DnsCacheUnlock() LeaveCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock); + +VOID +DnsIntCacheInitialize(VOID) +{ + /* Check if we're initialized */ + if (DnsCacheInitialized) + return; + /* Initialize the catalog lock and namespace list */ + InitializeCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock); + InitializeListHead(&DnsCache.RecordList); + DnsCacheInitialized = TRUE; +} + +VOID +DnsIntCacheFree(VOID) +{ + /* Check if we're initialized */ + if (!DnsCacheInitialized) + return; + if (!DnsCache.RecordList.Flink) + return; + + DnsIntCacheFlush(); + + DeleteCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock); + DnsCacheInitialized = FALSE; +} + +VOID +DnsIntCacheRemoveEntryItem(PTCACHE_ENTRY CacheEntry) +{ + /* Remove the entry from the list */ + RemoveEntryList(&CacheEntry->CacheLink); + + /* Free record */ + DnsRecordListFree((PDNS_RECORD)CacheEntry->Record, DnsFreeRecordList); + + /* Delete us */ + RtlFreeHeap(RtlGetProcessHeap(), 0, CacheEntry); + + /* Decrease our count */ + DnsCache.ItemCount--; +} + +VOID +DnsIntCacheFlush(VOID) +{ + PLIST_ENTRY Entry; + PTCACHE_ENTRY CacheEntry; + + /* Acquire lock */ + DnsCacheLock(); + + /* Loop every entry */ + Entry = DnsCache.RecordList.Flink; + while (Entry != &DnsCache.RecordList) + { + /* Get this entry */ + CacheEntry = CONTAINING_RECORD(Entry, TCACHE_ENTRY, CacheLink); + + /* Remove it from list */ + DnsIntCacheRemoveEntryItem(CacheEntry); + + /* Move to the next entry */ + Entry = DnsCache.RecordList.Flink; + } + + /* Release and delete the lock */ + DnsCacheUnlock(); +} + +BOOL +DnsIntCacheGetEntryFromName(LPCWSTR Name, + PDNS_RECORDW *Record) +{ + BOOL Ret = FALSE; + PLIST_ENTRY NextEntry = DnsCache.RecordList.Flink; + PTCACHE_ENTRY Entry; + + /* Assume failure */ + *Record = NULL; + + /* Lock the cache */ + DnsCacheLock(); + + /* Match the Id with all the entries in the List */ + while (NextEntry != &DnsCache.RecordList) + { + /* Get the Current Entry */ + Entry = CONTAINING_RECORD(NextEntry, TCACHE_ENTRY, CacheLink); + NextEntry = NextEntry->Flink; + + /* Check if this is the Catalog Entry ID we want */ + if (_wcsnicmp(Entry->Record->pName, Name, NI_MAXHOST) == 0) + { + /* Copy the entry and return it */ + *Record = (PDNS_RECORDW)DnsRecordCopyEx((PDNS_RECORD)Entry->Record, DnsCharSetUnicode, DnsCharSetUnicode); + Ret = TRUE; + break; + } + } + + /* Release the catalog */ + DnsCacheUnlock(); + + /* Return */ + return Ret; +} + +BOOL +DnsIntCacheRemoveEntryByName(LPCWSTR Name) +{ + BOOL Ret = FALSE; + PLIST_ENTRY NextEntry = DnsCache.RecordList.Flink; + PTCACHE_ENTRY Entry; + + /* Lock the cache */ + DnsCacheLock(); + + /* Match the Id with all the entries in the List */ + while (NextEntry != &DnsCache.RecordList) + { + /* Get the Current Entry */ + Entry = CONTAINING_RECORD(NextEntry, TCACHE_ENTRY, CacheLink); + NextEntry = NextEntry->Flink; + + /* Check if this is the Catalog Entry ID we want */ + if (_wcsnicmp(Entry->Record->pName, Name, NI_MAXHOST) == 0) + { + /* Copy the entry and return it */ + DnsIntCacheRemoveEntryItem(Entry); + Ret = TRUE; + break; + } + } + + /* Release the catalog */ + DnsCacheUnlock(); + + /* Return */ + return Ret; +} + +VOID +DnsIntCacheAddEntry(PDNS_RECORDW Record) +{ + PTCACHE_ENTRY Entry; + + /* Lock the cache */ + DnsCacheLock(); + + /* Match the Id with all the entries in the List */ + Entry = (PTCACHE_ENTRY)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Entry)); + if (!Entry) + return; + Entry->Record = Record; + + /* Insert it to our List */ + InsertTailList(&DnsCache.RecordList, &Entry->CacheLink); + + /* Increase our count */ + DnsCache.ItemCount++; + + /* Release the catalog */ + DnsCacheUnlock(); +} Index: dll/win32/dnsrslvr/dnsrslvr.h =================================================================== --- dll/win32/dnsrslvr/dnsrslvr.h (revision 0) +++ dll/win32/dnsrslvr/dnsrslvr.h (working copy) @@ -0,0 +1,86 @@ +#ifndef DNSRSLVR_INTERNAL_H +#define DNSRSLVR_INTERNAL_H + +typedef struct _TCACHE_ENTRY +{ + LIST_ENTRY CacheLink; + PDNS_RECORDW Record; +} TCACHE_ENTRY, *PTCACHE_ENTRY; + +typedef struct _TCACHE +{ + LIST_ENTRY RecordList; + DWORD ItemCount; + RTL_CRITICAL_SECTION Lock; +} TCACHE, *PTCACHE; + +VOID DnsIntCacheInitialize(VOID); +VOID DnsIntCacheRemoveEntryItem(PTCACHE_ENTRY CacheEntry); +VOID DnsIntCacheFree(VOID); +VOID DnsIntCacheFlush(VOID); +BOOL DnsIntCacheGetEntryFromName(LPCWSTR Name, + PDNS_RECORDW *Record); +VOID DnsIntCacheAddEntry(PDNS_RECORDW Record); +BOOL DnsIntCacheRemoveEntryByName(LPCWSTR Name); + +/* pipe operations */ +enum +{ + DnsReqQueryRecord, + DnsReqAddRecord, + DnsReqRemoveRecord, + DnsReqFlushAllRecords, +}; + +/* pipe communication structures */ +typedef struct _COMM_DNS_REQ +{ + UINT Type; + LPWSTR Name; + DNS_RECORDW Record; + BYTE Data[NI_MAXHOST*sizeof(WCHAR)]; +} COMM_DNS_REQ; + +typedef struct _COMM_DNS_REPLY +{ + DWORD Reply; + DNS_RECORDW Record; + BYTE Data[NI_MAXHOST*sizeof(WCHAR)]; +} COMM_DNS_REPLY; + +/* pipe name */ +#define DNS_PIPE_NAME L"\\\\.\\pipe\\dnsclient" + +#define COMM_PIPE_OUTPUT_BUFFER sizeof(COMM_DNS_REQ) +#define COMM_PIPE_INPUT_BUFFER sizeof(COMM_DNS_REPLY) +#define COMM_PIPE_DEFAULT_TIMEOUT 1000 + +typedef DWORD(*PipeSendFunc)(COMM_DNS_REPLY *Reply); + +/* these do the real work */ +DWORD DnsPipedQueryRecord(PipeSendFunc Send, COMM_DNS_REQ *Req); +DWORD DnsPipedAddRecord(PipeSendFunc Send, COMM_DNS_REQ *Req); +DWORD DnsPipedRemoveRecord(PipeSendFunc Send, COMM_DNS_REQ *Req); +DWORD DnsPipedFlushAllRecords(PipeSendFunc Send, COMM_DNS_REQ *Req); + +/* pipe internals */ +HANDLE PipeInit(VOID); +DWORD PipeSend(COMM_DNS_REPLY *Reply); +VOID PipeDestroy(VOID); + +/* Dns piped api */ +DWORD WINAPI +DnsCApiInitialize(LPHANDLE PipeHandle); +VOID WINAPI +DnsCApiCleanup(HANDLE PipeHandle); + +BOOL WINAPI +DnsCApiQueryRecord(HANDLE PipeHandle, LPCWSTR Name, PDNS_RECORDW *Record); +BOOL WINAPI +DnsCApiAddRecord(HANDLE PipeHandle, PDNS_RECORDW Record); +BOOL WINAPI +DnsCApiRemoveRecord(HANDLE PipeHandle, LPCWSTR Name); +BOOL WINAPI +DnsCApiFlushAllRecords(HANDLE PipeHandle); + +#endif /* DNSRSLVR_INTERNAL_H */ Index: dll/win32/dnsrslvr/dnsrslvr.rc =================================================================== --- dll/win32/dnsrslvr/dnsrslvr.rc (revision 0) +++ dll/win32/dnsrslvr/dnsrslvr.rc (working copy) @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "DNS Cache Service Library" +#define REACTOS_STR_INTERNAL_NAME "dnsrslvr" +#define REACTOS_STR_ORIGINAL_FILENAME "dnsrslvr.dll" +#include Index: dll/win32/dnsrslvr/dnsrslvr.spec =================================================================== --- dll/win32/dnsrslvr/dnsrslvr.spec (revision 0) +++ dll/win32/dnsrslvr/dnsrslvr.spec (working copy) @@ -0,0 +1,7 @@ +@ stdcall DnsCApiInitialize(ptr) +@ stdcall DnsCApiCleanup(long) +@ stdcall DnsCApiQueryRecord(long wstr ptr) +@ stdcall DnsCApiAddRecord(long ptr) +@ stdcall DnsCApiRemoveRecord(long wstr) +@ stdcall DnsCApiFlushAllRecords(long) +@ stdcall ServiceMain(long ptr) Index: dll/win32/dnsrslvr/pipe.c =================================================================== --- dll/win32/dnsrslvr/pipe.c (revision 0) +++ dll/win32/dnsrslvr/pipe.c (working copy) @@ -0,0 +1,113 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/pipe.c + * PURPOSE: DNS client pipe + * PROGRAMMER: Peter Hater + */ + +#include "precomp.h" + +#define NDEBUG +#include + +static HANDLE CommPipe = INVALID_HANDLE_VALUE, CommThread; +DWORD CommThrId; + +DWORD PipeSend(COMM_DNS_REPLY *Reply) +{ + DWORD Written = 0; + BOOL Success = WriteFile(CommPipe, + Reply, + sizeof(*Reply), + &Written, + NULL); + return Success ? Written : -1; +} + +DWORD WINAPI PipeThreadProc(LPVOID Parameter) +{ + DWORD BytesRead; + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + BOOL Result, Connected; + + while (TRUE) + { + Connected = ConnectNamedPipe(CommPipe, NULL) ? TRUE : GetLastError() == ERROR_PIPE_CONNECTED; + + if (!Connected) + { + DPRINT1("DNSRSLVR: Could not connect named pipe\n"); + CloseHandle(CommPipe); + CommPipe = INVALID_HANDLE_VALUE; + break; + } + + Result = ReadFile(CommPipe, &Req, sizeof(Req), &BytesRead, NULL); + if (Result) + { + switch (Req.Type) { + case DnsReqQueryRecord: + DnsPipedQueryRecord(PipeSend, &Req); + break; + + case DnsReqAddRecord: + DnsPipedAddRecord(PipeSend, &Req); + break; + + case DnsReqRemoveRecord: + DnsPipedRemoveRecord(PipeSend, &Req); + break; + + case DnsReqFlushAllRecords: + DnsPipedFlushAllRecords(PipeSend, &Req); + break; + + default: + DPRINT1("DNSRSLVR: Unrecognized request type %d\n", Req.Type); + ZeroMemory(&Reply, sizeof(COMM_DNS_REPLY)); + Reply.Reply = 0; + PipeSend(&Reply); + break; + } + } + DisconnectNamedPipe(CommPipe); + } + + return TRUE; +} + +HANDLE PipeInit(VOID) +{ + CommPipe = CreateNamedPipeW(DNS_PIPE_NAME, + PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 1, + COMM_PIPE_OUTPUT_BUFFER, + COMM_PIPE_INPUT_BUFFER, + COMM_PIPE_DEFAULT_TIMEOUT, + NULL); + + if (CommPipe == INVALID_HANDLE_VALUE) + { + DPRINT("DNSRSLVR: Could not create named pipe\n"); + return CommPipe; + } + + CommThread = CreateThread(NULL, 0, PipeThreadProc, NULL, 0, &CommThrId); + + if (!CommThread) + { + CloseHandle(CommPipe); + CommPipe = INVALID_HANDLE_VALUE; + } + + return CommPipe; +} + +VOID PipeDestroy(VOID) +{ + CloseHandle(CommPipe); + CommPipe = INVALID_HANDLE_VALUE; +} Index: dll/win32/dnsrslvr/precomp.h =================================================================== --- dll/win32/dnsrslvr/precomp.h (revision 0) +++ dll/win32/dnsrslvr/precomp.h (working copy) @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS System Libraries + * FILE: lib/dnsrslvr/precomp.h + * PURPOSE: Win32 DNS Cache service Header + * PROGRAMMER: Peter Hater + */ + +#ifndef _DNSRSLVR_H +#define _DNSRSLVR_H + +/* INCLUDES ******************************************************************/ + +#include + +/* PSDK/NDK Headers */ +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H +#include +#include +#include +#include +#include +#define NTOS_MODE_USER +#include + +/* Internal DNSRSLVR Headers */ +#include "dnsrslvr.h" + +#endif /* _DNSRSLVR_H */ Index: dll/win32/dnsrslvr/service.c =================================================================== --- dll/win32/dnsrslvr/service.c (revision 0) +++ dll/win32/dnsrslvr/service.c (working copy) @@ -0,0 +1,375 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/service.c + * PURPOSE: DNSAPI service functions. + * PROGRAMER: Peter Hater + */ + +#include "precomp.h" +#include +#include + +#define NDEBUG +#include + +static WCHAR ServiceName[] = L"DNSCache"; + +SERVICE_STATUS_HANDLE ServiceStatusHandle = 0; +SERVICE_STATUS ServiceStatus; + +DWORD WINAPI +DnsCApiInitialize(LPHANDLE PipeHandle) +{ + DWORD PipeMode; + + if (!PipeHandle) + return ERROR_INVALID_PARAMETER; + + /* Wait for the pipe to be available */ + if (!WaitNamedPipeW(DNS_PIPE_NAME, NMPWAIT_USE_DEFAULT_WAIT)) + { + /* No good, we failed */ + return GetLastError(); + } + + /* It's available, let's try to open it */ + *PipeHandle = CreateFileW(DNS_PIPE_NAME, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + + /* Check if we succeeded in opening the pipe */ + if (*PipeHandle == INVALID_HANDLE_VALUE) + { + /* We didn't */ + return GetLastError(); + } + + /* Change the pipe into message mode */ + PipeMode = PIPE_READMODE_MESSAGE; + if (!SetNamedPipeHandleState(*PipeHandle, &PipeMode, NULL, NULL)) + { + /* Mode change failed */ + CloseHandle(*PipeHandle); + *PipeHandle = INVALID_HANDLE_VALUE; + return GetLastError(); + } + + /* We're good to go */ + return NO_ERROR; +} + +VOID WINAPI +DnsCApiCleanup(HANDLE PipeHandle) +{ + CloseHandle(PipeHandle); +} + +BOOL WINAPI +DnsCApiQueryRecord(HANDLE PipeHandle, LPCWSTR Name, PDNS_RECORDW* Record) +{ + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + DWORD BytesRead; + BOOL Result; + + ASSERT(PipeHandle != INVALID_HANDLE_VALUE); + + Req.Type = DnsReqQueryRecord; + /* Fix up pointers for sending */ + Req.Name = (LPWSTR)Req.Data; + StringCchCopy(Req.Name, NI_MAXHOST, Name); + + Result = TransactNamedPipe(PipeHandle, + &Req, sizeof(Req), + &Reply, sizeof(Reply), + &BytesRead, NULL); + if (!Result) + { + /* Pipe transaction failed */ + return FALSE; + } + + if (!Reply.Reply) + { + /* Request failed */ + return FALSE; + } + + if (Record) + { + /* Fix up pointers after receive */ + Reply.Record.pName = (LPWSTR)Reply.Data; + *Record = (PDNS_RECORDW)DnsRecordCopyEx((PDNS_RECORD)&Reply.Record, DnsCharSetUnicode, DnsCharSetUnicode); + } + + return TRUE; +} + +BOOL WINAPI +DnsCApiRemoveRecord(HANDLE PipeHandle, LPCWSTR Name) +{ + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + DWORD BytesRead; + BOOL Result; + + ASSERT(PipeHandle != INVALID_HANDLE_VALUE); + + Req.Type = DnsReqRemoveRecord; + /* Fix up pointers for sending */ + Req.Name = (LPWSTR)Req.Data; + StringCchCopy(Req.Name, NI_MAXHOST, Name); + + Result = TransactNamedPipe(PipeHandle, + &Req, sizeof(Req), + &Reply, sizeof(Reply), + &BytesRead, NULL); + if (!Result) + { + /* Pipe transaction failed */ + return FALSE; + } + + if (!Reply.Reply) + { + /* Request failed */ + return FALSE; + } + + return TRUE; +} + +BOOL WINAPI +DnsCApiAddRecord(HANDLE PipeHandle, PDNS_RECORDW Record) +{ + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + DWORD BytesRead; + BOOL Result; + + ASSERT(PipeHandle != INVALID_HANDLE_VALUE); + ASSERT(Record != NULL); + + Req.Type = DnsReqAddRecord; + RtlCopyMemory(&Req.Record, Record, sizeof(DNS_RECORDW)); + /* FIXME: Currently only record without names in DNS_RECORD.Data */ + RtlCopyMemory(&Req.Record.Data, &Record->Data, Record->wDataLength); + /* Fix up pointers for sending */ + Req.Record.pName = (LPWSTR)Req.Data; + StringCchCopy(Req.Record.pName, NI_MAXHOST, Record->pName); + + Result = TransactNamedPipe(PipeHandle, + &Req, sizeof(Req), + &Reply, sizeof(Reply), + &BytesRead, NULL); + if (!Result) + { + /* Pipe transaction failed */ + return FALSE; + } + + if (!Reply.Reply) + { + /* Request failed */ + return FALSE; + } + + return TRUE; +} + +BOOL WINAPI +DnsCApiFlushAllRecords(HANDLE PipeHandle) +{ + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + DWORD BytesRead; + BOOL Result; + + ASSERT(PipeHandle != INVALID_HANDLE_VALUE); + + Req.Type = DnsReqFlushAllRecords; + + Result = TransactNamedPipe(PipeHandle, + &Req, sizeof(Req), + &Reply, sizeof(Reply), + &BytesRead, NULL); + if (!Result) + { + /* Pipe transaction failed */ + return FALSE; + } + + if (!Reply.Reply) + { + /* Request failed */ + return FALSE; + } + + return TRUE; +} + +DWORD +DnsPipedQueryRecord(PipeSendFunc Send, COMM_DNS_REQ *Req) +{ + COMM_DNS_REPLY Reply; + PDNS_RECORDW TempDnsRecord; + + /* Fix up pointers after receive */ + Req->Name = (LPWSTR)Req->Data; + Reply.Reply = DnsIntCacheGetEntryFromName(Req->Name, &TempDnsRecord); // TRUE/FALSE ret + if (Reply.Reply) + { + /* FIXME: Fixup record names in DNS_RECORD.Data and add it the size */ + RtlCopyMemory(&Reply.Record, TempDnsRecord, sizeof(DNS_RECORDW)); + RtlCopyMemory(&Reply.Record.Data, &TempDnsRecord->Data, TempDnsRecord->wDataLength); + /* Fix up pointers for sending */ + Reply.Record.pName = (LPWSTR)Reply.Data; + StringCchCopy(Reply.Record.pName, NI_MAXHOST, TempDnsRecord->pName); + DnsRecordListFree((PDNS_RECORD)TempDnsRecord, DnsFreeRecordList); + } + return Send(&Reply); +} + +DWORD +DnsPipedRemoveRecord(PipeSendFunc Send, COMM_DNS_REQ *Req) +{ + COMM_DNS_REPLY Reply; + + /* Fix up pointers after receive */ + Req->Name = (LPWSTR)Req->Data; + Reply.Reply = DnsIntCacheRemoveEntryByName(Req->Name); // TRUE/FALSE ret + return Send(&Reply); +} + +DWORD +DnsPipedAddRecord(PipeSendFunc Send, COMM_DNS_REQ *Req) +{ + COMM_DNS_REPLY Reply; + PDNS_RECORDW Record; + + /* Fix up pointers after receive */ + Req->Record.pName = (LPWSTR)Req->Data; + Record = (PDNS_RECORDW)DnsRecordCopyEx((PDNS_RECORD)&Req->Record, DnsCharSetUnicode, DnsCharSetUnicode); + DnsIntCacheAddEntry(Record); + Reply.Reply = 1; // TRUE/FALSE ret + + return Send(&Reply); +} + +DWORD +DnsPipedFlushAllRecords(PipeSendFunc Send, COMM_DNS_REQ *Req) +{ + COMM_DNS_REPLY Reply; + + DnsIntCacheFlush(); + Reply.Reply = 1; // TRUE/FALSE ret + + return Send(&Reply); +} + +static VOID +UpdateServiceStatus(DWORD dwState) +{ + ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStatus.dwCurrentState = dwState; + + ServiceStatus.dwControlsAccepted = 0; + + ServiceStatus.dwWin32ExitCode = 0; + ServiceStatus.dwServiceSpecificExitCode = 0; + ServiceStatus.dwCheckPoint = 0; + + if (dwState == SERVICE_START_PENDING || + dwState == SERVICE_STOP_PENDING || + dwState == SERVICE_PAUSE_PENDING || + dwState == SERVICE_CONTINUE_PENDING) + ServiceStatus.dwWaitHint = 10000; + else + ServiceStatus.dwWaitHint = 0; + + SetServiceStatus(ServiceStatusHandle, &ServiceStatus); +} + +static DWORD WINAPI +ServiceControlHandler(DWORD dwControl, + DWORD dwEventType, + LPVOID lpEventData, + LPVOID lpContext) +{ + switch (dwControl) + { + case SERVICE_CONTROL_STOP: + UpdateServiceStatus(SERVICE_STOP_PENDING); + DPRINT("DNSRSLVR: DNS Client Service is shutting down\n"); + PipeDestroy(); + DnsIntCacheFree(); + UpdateServiceStatus(SERVICE_STOPPED); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_PAUSE: + UpdateServiceStatus(SERVICE_PAUSE_PENDING); + PipeDestroy(); + UpdateServiceStatus(SERVICE_PAUSED); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_CONTINUE: + UpdateServiceStatus(SERVICE_START_PENDING); + if (PipeInit() == INVALID_HANDLE_VALUE) + { + DPRINT1("DNSRSLVR: PipeInit() failed!\n"); + UpdateServiceStatus(SERVICE_STOPPED); + return ERROR_PIPE_NOT_CONNECTED; // FALSE + } + UpdateServiceStatus(SERVICE_RUNNING); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_INTERROGATE: + SetServiceStatus(ServiceStatusHandle, &ServiceStatus); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_SHUTDOWN: + UpdateServiceStatus(SERVICE_STOP_PENDING); + DPRINT("DNSRSLVR: DNS Client Service is shutting down\n"); + PipeDestroy(); + DnsIntCacheFree(); + UpdateServiceStatus(SERVICE_STOPPED); + return ERROR_SUCCESS; + + default: + return ERROR_CALL_NOT_IMPLEMENTED; + } +} + +VOID WINAPI +ServiceMain(DWORD argc, LPWSTR* argv) +{ + ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, + ServiceControlHandler, + NULL); + if (!ServiceStatusHandle) + { + DPRINT1("DNSRSLVR: Unable to register service control handler (%lx)\n", GetLastError()); + return; // FALSE + } + + UpdateServiceStatus(SERVICE_START_PENDING); + + DnsIntCacheInitialize(); + + if (PipeInit() == INVALID_HANDLE_VALUE) + { + DPRINT1("DNSAPISVC: PipeInit() failed!\n"); + DnsIntCacheFree(); + UpdateServiceStatus(SERVICE_STOPPED); + return; // FALSE + } + + DPRINT("DNSRSLVR: DNS Client Service Started\n"); + + UpdateServiceStatus(SERVICE_RUNNING); +} Index: dll/win32/dnsrslvr =================================================================== --- dll/win32/dnsrslvr (revision 0) +++ dll/win32/dnsrslvr (working copy) Property changes on: dll/win32/dnsrslvr ___________________________________________________________________ Added: bugtraq:message ## -0,0 +1 ## +See issue %BUGID% for more details. \ No newline at end of property Added: tsvn:logminsize ## -0,0 +1 ## +10 \ No newline at end of property Added: bugtraq:logregex ## -0,0 +1 ## +((CORE|ROSTESTS|ROSAPPS)-\d+)(,? ?((CORE|ROSTESTS|ROSAPPS)-\d+))*(,? ?(and |or )?((CORE|ROSTESTS|ROSAPPS)-\d+))? Added: bugtraq:url ## -0,0 +1 ## +https://jira.reactos.org/browse/%BUGID% \ No newline at end of property Index: dll/win32/dnsrslvr/cache.c =================================================================== --- dll/win32/dnsrslvr/cache.c (revision 0) +++ dll/win32/dnsrslvr/cache.c (working copy) @@ -0,0 +1,185 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/cache.c + * PURPOSE: DNSAPI cache functions. + * PROGRAMER: Peter Hater + */ + +#include "precomp.h" +#include + +#define NDEBUG +#include + +static TCACHE DnsCache; +static BOOL DnsCacheInitialized = FALSE; + +#define DnsCacheLock() EnterCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock); +#define DnsCacheUnlock() LeaveCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock); + +VOID +DnsIntCacheInitialize(VOID) +{ + /* Check if we're initialized */ + if (DnsCacheInitialized) + return; + /* Initialize the catalog lock and namespace list */ + InitializeCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock); + InitializeListHead(&DnsCache.RecordList); + DnsCacheInitialized = TRUE; +} + +VOID +DnsIntCacheFree(VOID) +{ + /* Check if we're initialized */ + if (!DnsCacheInitialized) + return; + if (!DnsCache.RecordList.Flink) + return; + + DnsIntCacheFlush(); + + DeleteCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock); + DnsCacheInitialized = FALSE; +} + +VOID +DnsIntCacheRemoveEntryItem(PTCACHE_ENTRY CacheEntry) +{ + /* Remove the entry from the list */ + RemoveEntryList(&CacheEntry->CacheLink); + + /* Free record */ + DnsRecordListFree((PDNS_RECORD)CacheEntry->Record, DnsFreeRecordList); + + /* Delete us */ + RtlFreeHeap(RtlGetProcessHeap(), 0, CacheEntry); + + /* Decrease our count */ + DnsCache.ItemCount--; +} + +VOID +DnsIntCacheFlush(VOID) +{ + PLIST_ENTRY Entry; + PTCACHE_ENTRY CacheEntry; + + /* Acquire lock */ + DnsCacheLock(); + + /* Loop every entry */ + Entry = DnsCache.RecordList.Flink; + while (Entry != &DnsCache.RecordList) + { + /* Get this entry */ + CacheEntry = CONTAINING_RECORD(Entry, TCACHE_ENTRY, CacheLink); + + /* Remove it from list */ + DnsIntCacheRemoveEntryItem(CacheEntry); + + /* Move to the next entry */ + Entry = DnsCache.RecordList.Flink; + } + + /* Release and delete the lock */ + DnsCacheUnlock(); +} + +BOOL +DnsIntCacheGetEntryFromName(LPCWSTR Name, + PDNS_RECORDW *Record) +{ + BOOL Ret = FALSE; + PLIST_ENTRY NextEntry = DnsCache.RecordList.Flink; + PTCACHE_ENTRY Entry; + + /* Assume failure */ + *Record = NULL; + + /* Lock the cache */ + DnsCacheLock(); + + /* Match the Id with all the entries in the List */ + while (NextEntry != &DnsCache.RecordList) + { + /* Get the Current Entry */ + Entry = CONTAINING_RECORD(NextEntry, TCACHE_ENTRY, CacheLink); + NextEntry = NextEntry->Flink; + + /* Check if this is the Catalog Entry ID we want */ + if (_wcsnicmp(Entry->Record->pName, Name, NI_MAXHOST) == 0) + { + /* Copy the entry and return it */ + *Record = (PDNS_RECORDW)DnsRecordCopyEx((PDNS_RECORD)Entry->Record, DnsCharSetUnicode, DnsCharSetUnicode); + Ret = TRUE; + break; + } + } + + /* Release the catalog */ + DnsCacheUnlock(); + + /* Return */ + return Ret; +} + +BOOL +DnsIntCacheRemoveEntryByName(LPCWSTR Name) +{ + BOOL Ret = FALSE; + PLIST_ENTRY NextEntry = DnsCache.RecordList.Flink; + PTCACHE_ENTRY Entry; + + /* Lock the cache */ + DnsCacheLock(); + + /* Match the Id with all the entries in the List */ + while (NextEntry != &DnsCache.RecordList) + { + /* Get the Current Entry */ + Entry = CONTAINING_RECORD(NextEntry, TCACHE_ENTRY, CacheLink); + NextEntry = NextEntry->Flink; + + /* Check if this is the Catalog Entry ID we want */ + if (_wcsnicmp(Entry->Record->pName, Name, NI_MAXHOST) == 0) + { + /* Copy the entry and return it */ + DnsIntCacheRemoveEntryItem(Entry); + Ret = TRUE; + break; + } + } + + /* Release the catalog */ + DnsCacheUnlock(); + + /* Return */ + return Ret; +} + +VOID +DnsIntCacheAddEntry(PDNS_RECORDW Record) +{ + PTCACHE_ENTRY Entry; + + /* Lock the cache */ + DnsCacheLock(); + + /* Match the Id with all the entries in the List */ + Entry = (PTCACHE_ENTRY)RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Entry)); + if (!Entry) + return; + Entry->Record = Record; + + /* Insert it to our List */ + InsertTailList(&DnsCache.RecordList, &Entry->CacheLink); + + /* Increase our count */ + DnsCache.ItemCount++; + + /* Release the catalog */ + DnsCacheUnlock(); +} Index: dll/win32/dnsrslvr/CMakeLists.txt =================================================================== --- dll/win32/dnsrslvr/CMakeLists.txt (revision 0) +++ dll/win32/dnsrslvr/CMakeLists.txt (working copy) @@ -0,0 +1,17 @@ +spec2def(dnsrslvr.dll dnsrslvr.spec ADD_IMPORTLIB) + +list(APPEND SOURCE + cache.c + pipe.c + service.c + precomp.h) + +add_library(dnsrslvr SHARED + ${SOURCE} + dnsrslvr.rc + ${CMAKE_CURRENT_BINARY_DIR}/dnsrslvr.def) + +set_module_type(dnsrslvr win32dll) +add_importlibs(dnsrslvr advapi32 dnsapi msvcrt kernel32 ntdll) +add_pch(dnsrslvr precomp.h SOURCE) +add_cd_file(TARGET dnsrslvr DESTINATION reactos/system32 FOR all) Index: dll/win32/dnsrslvr/dnsrslvr.h =================================================================== --- dll/win32/dnsrslvr/dnsrslvr.h (revision 0) +++ dll/win32/dnsrslvr/dnsrslvr.h (working copy) @@ -0,0 +1,86 @@ +#ifndef DNSRSLVR_INTERNAL_H +#define DNSRSLVR_INTERNAL_H + +typedef struct _TCACHE_ENTRY +{ + LIST_ENTRY CacheLink; + PDNS_RECORDW Record; +} TCACHE_ENTRY, *PTCACHE_ENTRY; + +typedef struct _TCACHE +{ + LIST_ENTRY RecordList; + DWORD ItemCount; + RTL_CRITICAL_SECTION Lock; +} TCACHE, *PTCACHE; + +VOID DnsIntCacheInitialize(VOID); +VOID DnsIntCacheRemoveEntryItem(PTCACHE_ENTRY CacheEntry); +VOID DnsIntCacheFree(VOID); +VOID DnsIntCacheFlush(VOID); +BOOL DnsIntCacheGetEntryFromName(LPCWSTR Name, + PDNS_RECORDW *Record); +VOID DnsIntCacheAddEntry(PDNS_RECORDW Record); +BOOL DnsIntCacheRemoveEntryByName(LPCWSTR Name); + +/* pipe operations */ +enum +{ + DnsReqQueryRecord, + DnsReqAddRecord, + DnsReqRemoveRecord, + DnsReqFlushAllRecords, +}; + +/* pipe communication structures */ +typedef struct _COMM_DNS_REQ +{ + UINT Type; + LPWSTR Name; + DNS_RECORDW Record; + BYTE Data[NI_MAXHOST*sizeof(WCHAR)]; +} COMM_DNS_REQ; + +typedef struct _COMM_DNS_REPLY +{ + DWORD Reply; + DNS_RECORDW Record; + BYTE Data[NI_MAXHOST*sizeof(WCHAR)]; +} COMM_DNS_REPLY; + +/* pipe name */ +#define DNS_PIPE_NAME L"\\\\.\\pipe\\dnsclient" + +#define COMM_PIPE_OUTPUT_BUFFER sizeof(COMM_DNS_REQ) +#define COMM_PIPE_INPUT_BUFFER sizeof(COMM_DNS_REPLY) +#define COMM_PIPE_DEFAULT_TIMEOUT 1000 + +typedef DWORD(*PipeSendFunc)(COMM_DNS_REPLY *Reply); + +/* these do the real work */ +DWORD DnsPipedQueryRecord(PipeSendFunc Send, COMM_DNS_REQ *Req); +DWORD DnsPipedAddRecord(PipeSendFunc Send, COMM_DNS_REQ *Req); +DWORD DnsPipedRemoveRecord(PipeSendFunc Send, COMM_DNS_REQ *Req); +DWORD DnsPipedFlushAllRecords(PipeSendFunc Send, COMM_DNS_REQ *Req); + +/* pipe internals */ +HANDLE PipeInit(VOID); +DWORD PipeSend(COMM_DNS_REPLY *Reply); +VOID PipeDestroy(VOID); + +/* Dns piped api */ +DWORD WINAPI +DnsCApiInitialize(LPHANDLE PipeHandle); +VOID WINAPI +DnsCApiCleanup(HANDLE PipeHandle); + +BOOL WINAPI +DnsCApiQueryRecord(HANDLE PipeHandle, LPCWSTR Name, PDNS_RECORDW *Record); +BOOL WINAPI +DnsCApiAddRecord(HANDLE PipeHandle, PDNS_RECORDW Record); +BOOL WINAPI +DnsCApiRemoveRecord(HANDLE PipeHandle, LPCWSTR Name); +BOOL WINAPI +DnsCApiFlushAllRecords(HANDLE PipeHandle); + +#endif /* DNSRSLVR_INTERNAL_H */ Index: dll/win32/dnsrslvr/dnsrslvr.rc =================================================================== --- dll/win32/dnsrslvr/dnsrslvr.rc (revision 0) +++ dll/win32/dnsrslvr/dnsrslvr.rc (working copy) @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "DNS Cache Service Library" +#define REACTOS_STR_INTERNAL_NAME "dnsrslvr" +#define REACTOS_STR_ORIGINAL_FILENAME "dnsrslvr.dll" +#include Index: dll/win32/dnsrslvr/dnsrslvr.spec =================================================================== --- dll/win32/dnsrslvr/dnsrslvr.spec (revision 0) +++ dll/win32/dnsrslvr/dnsrslvr.spec (working copy) @@ -0,0 +1,7 @@ +@ stdcall DnsCApiInitialize(ptr) +@ stdcall DnsCApiCleanup(long) +@ stdcall DnsCApiQueryRecord(long wstr ptr) +@ stdcall DnsCApiAddRecord(long ptr) +@ stdcall DnsCApiRemoveRecord(long wstr) +@ stdcall DnsCApiFlushAllRecords(long) +@ stdcall ServiceMain(long ptr) Index: dll/win32/dnsrslvr/pipe.c =================================================================== --- dll/win32/dnsrslvr/pipe.c (revision 0) +++ dll/win32/dnsrslvr/pipe.c (working copy) @@ -0,0 +1,113 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/pipe.c + * PURPOSE: DNS client pipe + * PROGRAMMER: Peter Hater + */ + +#include "precomp.h" + +#define NDEBUG +#include + +static HANDLE CommPipe = INVALID_HANDLE_VALUE, CommThread; +DWORD CommThrId; + +DWORD PipeSend(COMM_DNS_REPLY *Reply) +{ + DWORD Written = 0; + BOOL Success = WriteFile(CommPipe, + Reply, + sizeof(*Reply), + &Written, + NULL); + return Success ? Written : -1; +} + +DWORD WINAPI PipeThreadProc(LPVOID Parameter) +{ + DWORD BytesRead; + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + BOOL Result, Connected; + + while (TRUE) + { + Connected = ConnectNamedPipe(CommPipe, NULL) ? TRUE : GetLastError() == ERROR_PIPE_CONNECTED; + + if (!Connected) + { + DPRINT1("DNSRSLVR: Could not connect named pipe\n"); + CloseHandle(CommPipe); + CommPipe = INVALID_HANDLE_VALUE; + break; + } + + Result = ReadFile(CommPipe, &Req, sizeof(Req), &BytesRead, NULL); + if (Result) + { + switch (Req.Type) { + case DnsReqQueryRecord: + DnsPipedQueryRecord(PipeSend, &Req); + break; + + case DnsReqAddRecord: + DnsPipedAddRecord(PipeSend, &Req); + break; + + case DnsReqRemoveRecord: + DnsPipedRemoveRecord(PipeSend, &Req); + break; + + case DnsReqFlushAllRecords: + DnsPipedFlushAllRecords(PipeSend, &Req); + break; + + default: + DPRINT1("DNSRSLVR: Unrecognized request type %d\n", Req.Type); + ZeroMemory(&Reply, sizeof(COMM_DNS_REPLY)); + Reply.Reply = 0; + PipeSend(&Reply); + break; + } + } + DisconnectNamedPipe(CommPipe); + } + + return TRUE; +} + +HANDLE PipeInit(VOID) +{ + CommPipe = CreateNamedPipeW(DNS_PIPE_NAME, + PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + 1, + COMM_PIPE_OUTPUT_BUFFER, + COMM_PIPE_INPUT_BUFFER, + COMM_PIPE_DEFAULT_TIMEOUT, + NULL); + + if (CommPipe == INVALID_HANDLE_VALUE) + { + DPRINT("DNSRSLVR: Could not create named pipe\n"); + return CommPipe; + } + + CommThread = CreateThread(NULL, 0, PipeThreadProc, NULL, 0, &CommThrId); + + if (!CommThread) + { + CloseHandle(CommPipe); + CommPipe = INVALID_HANDLE_VALUE; + } + + return CommPipe; +} + +VOID PipeDestroy(VOID) +{ + CloseHandle(CommPipe); + CommPipe = INVALID_HANDLE_VALUE; +} Index: dll/win32/dnsrslvr/precomp.h =================================================================== --- dll/win32/dnsrslvr/precomp.h (revision 0) +++ dll/win32/dnsrslvr/precomp.h (working copy) @@ -0,0 +1,31 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS System Libraries + * FILE: lib/dnsrslvr/precomp.h + * PURPOSE: Win32 DNS Cache service Header + * PROGRAMMER: Peter Hater + */ + +#ifndef _DNSRSLVR_H +#define _DNSRSLVR_H + +/* INCLUDES ******************************************************************/ + +#include + +/* PSDK/NDK Headers */ +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H +#include +#include +#include +#include +#include +#define NTOS_MODE_USER +#include + +/* Internal DNSRSLVR Headers */ +#include "dnsrslvr.h" + +#endif /* _DNSRSLVR_H */ Index: dll/win32/dnsrslvr/service.c =================================================================== --- dll/win32/dnsrslvr/service.c (revision 0) +++ dll/win32/dnsrslvr/service.c (working copy) @@ -0,0 +1,375 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * FILE: lib/dnsapi/dnsapi/service.c + * PURPOSE: DNSAPI service functions. + * PROGRAMER: Peter Hater + */ + +#include "precomp.h" +#include +#include + +#define NDEBUG +#include + +static WCHAR ServiceName[] = L"DNSCache"; + +SERVICE_STATUS_HANDLE ServiceStatusHandle = 0; +SERVICE_STATUS ServiceStatus; + +DWORD WINAPI +DnsCApiInitialize(LPHANDLE PipeHandle) +{ + DWORD PipeMode; + + if (!PipeHandle) + return ERROR_INVALID_PARAMETER; + + /* Wait for the pipe to be available */ + if (!WaitNamedPipeW(DNS_PIPE_NAME, NMPWAIT_USE_DEFAULT_WAIT)) + { + /* No good, we failed */ + return GetLastError(); + } + + /* It's available, let's try to open it */ + *PipeHandle = CreateFileW(DNS_PIPE_NAME, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + + /* Check if we succeeded in opening the pipe */ + if (*PipeHandle == INVALID_HANDLE_VALUE) + { + /* We didn't */ + return GetLastError(); + } + + /* Change the pipe into message mode */ + PipeMode = PIPE_READMODE_MESSAGE; + if (!SetNamedPipeHandleState(*PipeHandle, &PipeMode, NULL, NULL)) + { + /* Mode change failed */ + CloseHandle(*PipeHandle); + *PipeHandle = INVALID_HANDLE_VALUE; + return GetLastError(); + } + + /* We're good to go */ + return NO_ERROR; +} + +VOID WINAPI +DnsCApiCleanup(HANDLE PipeHandle) +{ + CloseHandle(PipeHandle); +} + +BOOL WINAPI +DnsCApiQueryRecord(HANDLE PipeHandle, LPCWSTR Name, PDNS_RECORDW* Record) +{ + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + DWORD BytesRead; + BOOL Result; + + ASSERT(PipeHandle != INVALID_HANDLE_VALUE); + + Req.Type = DnsReqQueryRecord; + /* Fix up pointers for sending */ + Req.Name = (LPWSTR)Req.Data; + StringCchCopy(Req.Name, NI_MAXHOST, Name); + + Result = TransactNamedPipe(PipeHandle, + &Req, sizeof(Req), + &Reply, sizeof(Reply), + &BytesRead, NULL); + if (!Result) + { + /* Pipe transaction failed */ + return FALSE; + } + + if (!Reply.Reply) + { + /* Request failed */ + return FALSE; + } + + if (Record) + { + /* Fix up pointers after receive */ + Reply.Record.pName = (LPWSTR)Reply.Data; + *Record = (PDNS_RECORDW)DnsRecordCopyEx((PDNS_RECORD)&Reply.Record, DnsCharSetUnicode, DnsCharSetUnicode); + } + + return TRUE; +} + +BOOL WINAPI +DnsCApiRemoveRecord(HANDLE PipeHandle, LPCWSTR Name) +{ + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + DWORD BytesRead; + BOOL Result; + + ASSERT(PipeHandle != INVALID_HANDLE_VALUE); + + Req.Type = DnsReqRemoveRecord; + /* Fix up pointers for sending */ + Req.Name = (LPWSTR)Req.Data; + StringCchCopy(Req.Name, NI_MAXHOST, Name); + + Result = TransactNamedPipe(PipeHandle, + &Req, sizeof(Req), + &Reply, sizeof(Reply), + &BytesRead, NULL); + if (!Result) + { + /* Pipe transaction failed */ + return FALSE; + } + + if (!Reply.Reply) + { + /* Request failed */ + return FALSE; + } + + return TRUE; +} + +BOOL WINAPI +DnsCApiAddRecord(HANDLE PipeHandle, PDNS_RECORDW Record) +{ + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + DWORD BytesRead; + BOOL Result; + + ASSERT(PipeHandle != INVALID_HANDLE_VALUE); + ASSERT(Record != NULL); + + Req.Type = DnsReqAddRecord; + RtlCopyMemory(&Req.Record, Record, sizeof(DNS_RECORDW)); + /* FIXME: Currently only record without names in DNS_RECORD.Data */ + RtlCopyMemory(&Req.Record.Data, &Record->Data, Record->wDataLength); + /* Fix up pointers for sending */ + Req.Record.pName = (LPWSTR)Req.Data; + StringCchCopy(Req.Record.pName, NI_MAXHOST, Record->pName); + + Result = TransactNamedPipe(PipeHandle, + &Req, sizeof(Req), + &Reply, sizeof(Reply), + &BytesRead, NULL); + if (!Result) + { + /* Pipe transaction failed */ + return FALSE; + } + + if (!Reply.Reply) + { + /* Request failed */ + return FALSE; + } + + return TRUE; +} + +BOOL WINAPI +DnsCApiFlushAllRecords(HANDLE PipeHandle) +{ + COMM_DNS_REQ Req; + COMM_DNS_REPLY Reply; + DWORD BytesRead; + BOOL Result; + + ASSERT(PipeHandle != INVALID_HANDLE_VALUE); + + Req.Type = DnsReqFlushAllRecords; + + Result = TransactNamedPipe(PipeHandle, + &Req, sizeof(Req), + &Reply, sizeof(Reply), + &BytesRead, NULL); + if (!Result) + { + /* Pipe transaction failed */ + return FALSE; + } + + if (!Reply.Reply) + { + /* Request failed */ + return FALSE; + } + + return TRUE; +} + +DWORD +DnsPipedQueryRecord(PipeSendFunc Send, COMM_DNS_REQ *Req) +{ + COMM_DNS_REPLY Reply; + PDNS_RECORDW TempDnsRecord; + + /* Fix up pointers after receive */ + Req->Name = (LPWSTR)Req->Data; + Reply.Reply = DnsIntCacheGetEntryFromName(Req->Name, &TempDnsRecord); // TRUE/FALSE ret + if (Reply.Reply) + { + /* FIXME: Fixup record names in DNS_RECORD.Data and add it the size */ + RtlCopyMemory(&Reply.Record, TempDnsRecord, sizeof(DNS_RECORDW)); + RtlCopyMemory(&Reply.Record.Data, &TempDnsRecord->Data, TempDnsRecord->wDataLength); + /* Fix up pointers for sending */ + Reply.Record.pName = (LPWSTR)Reply.Data; + StringCchCopy(Reply.Record.pName, NI_MAXHOST, TempDnsRecord->pName); + DnsRecordListFree((PDNS_RECORD)TempDnsRecord, DnsFreeRecordList); + } + return Send(&Reply); +} + +DWORD +DnsPipedRemoveRecord(PipeSendFunc Send, COMM_DNS_REQ *Req) +{ + COMM_DNS_REPLY Reply; + + /* Fix up pointers after receive */ + Req->Name = (LPWSTR)Req->Data; + Reply.Reply = DnsIntCacheRemoveEntryByName(Req->Name); // TRUE/FALSE ret + return Send(&Reply); +} + +DWORD +DnsPipedAddRecord(PipeSendFunc Send, COMM_DNS_REQ *Req) +{ + COMM_DNS_REPLY Reply; + PDNS_RECORDW Record; + + /* Fix up pointers after receive */ + Req->Record.pName = (LPWSTR)Req->Data; + Record = (PDNS_RECORDW)DnsRecordCopyEx((PDNS_RECORD)&Req->Record, DnsCharSetUnicode, DnsCharSetUnicode); + DnsIntCacheAddEntry(Record); + Reply.Reply = 1; // TRUE/FALSE ret + + return Send(&Reply); +} + +DWORD +DnsPipedFlushAllRecords(PipeSendFunc Send, COMM_DNS_REQ *Req) +{ + COMM_DNS_REPLY Reply; + + DnsIntCacheFlush(); + Reply.Reply = 1; // TRUE/FALSE ret + + return Send(&Reply); +} + +static VOID +UpdateServiceStatus(DWORD dwState) +{ + ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStatus.dwCurrentState = dwState; + + ServiceStatus.dwControlsAccepted = 0; + + ServiceStatus.dwWin32ExitCode = 0; + ServiceStatus.dwServiceSpecificExitCode = 0; + ServiceStatus.dwCheckPoint = 0; + + if (dwState == SERVICE_START_PENDING || + dwState == SERVICE_STOP_PENDING || + dwState == SERVICE_PAUSE_PENDING || + dwState == SERVICE_CONTINUE_PENDING) + ServiceStatus.dwWaitHint = 10000; + else + ServiceStatus.dwWaitHint = 0; + + SetServiceStatus(ServiceStatusHandle, &ServiceStatus); +} + +static DWORD WINAPI +ServiceControlHandler(DWORD dwControl, + DWORD dwEventType, + LPVOID lpEventData, + LPVOID lpContext) +{ + switch (dwControl) + { + case SERVICE_CONTROL_STOP: + UpdateServiceStatus(SERVICE_STOP_PENDING); + DPRINT("DNSRSLVR: DNS Client Service is shutting down\n"); + PipeDestroy(); + DnsIntCacheFree(); + UpdateServiceStatus(SERVICE_STOPPED); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_PAUSE: + UpdateServiceStatus(SERVICE_PAUSE_PENDING); + PipeDestroy(); + UpdateServiceStatus(SERVICE_PAUSED); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_CONTINUE: + UpdateServiceStatus(SERVICE_START_PENDING); + if (PipeInit() == INVALID_HANDLE_VALUE) + { + DPRINT1("DNSRSLVR: PipeInit() failed!\n"); + UpdateServiceStatus(SERVICE_STOPPED); + return ERROR_PIPE_NOT_CONNECTED; // FALSE + } + UpdateServiceStatus(SERVICE_RUNNING); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_INTERROGATE: + SetServiceStatus(ServiceStatusHandle, &ServiceStatus); + return ERROR_SUCCESS; + + case SERVICE_CONTROL_SHUTDOWN: + UpdateServiceStatus(SERVICE_STOP_PENDING); + DPRINT("DNSRSLVR: DNS Client Service is shutting down\n"); + PipeDestroy(); + DnsIntCacheFree(); + UpdateServiceStatus(SERVICE_STOPPED); + return ERROR_SUCCESS; + + default: + return ERROR_CALL_NOT_IMPLEMENTED; + } +} + +VOID WINAPI +ServiceMain(DWORD argc, LPWSTR* argv) +{ + ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, + ServiceControlHandler, + NULL); + if (!ServiceStatusHandle) + { + DPRINT1("DNSRSLVR: Unable to register service control handler (%lx)\n", GetLastError()); + return; // FALSE + } + + UpdateServiceStatus(SERVICE_START_PENDING); + + DnsIntCacheInitialize(); + + if (PipeInit() == INVALID_HANDLE_VALUE) + { + DPRINT1("DNSAPISVC: PipeInit() failed!\n"); + DnsIntCacheFree(); + UpdateServiceStatus(SERVICE_STOPPED); + return; // FALSE + } + + DPRINT("DNSRSLVR: DNS Client Service Started\n"); + + UpdateServiceStatus(SERVICE_RUNNING); +} Index: media/inf/nettcpip.inf =================================================================== --- media/inf/nettcpip.inf (revision 73120) +++ media/inf/nettcpip.inf (working copy) @@ -235,6 +235,7 @@ [MS_TCPIP.PrimaryInstall.Services] AddService = Tcpip, , tcpip_Service_Inst AddService = DHCP, , dhcp_Service_Inst +AddService = Dnscache, , dns_Service_Inst [tcpip_Service_Inst] ServiceType = 1 @@ -269,6 +270,20 @@ HKR,,"ObjectName",0x00000000,"LocalSystem" HKR,"Parameters","ServiceDll",0x00020000,"%SystemRoot%\system32\dhcpcsvc.dll" +[dns_Service_Inst] +DisplayName = "DNS Client" +Description = "Service that caches local DNS queries" +ServiceType = 0x20 +StartType = 2 +ErrorControl = 1 +ServiceBinary = "%11%\svchost.exe -k netsvcs" +LoadOrderGroup = TDI +AddReg=dns_AddReg + +[dns_AddReg] +HKR,,"ObjectName",0x00000000,"LocalSystem" +HKR,"Parameters","ServiceDll",0x00020000,"%SystemRoot%\system32\dnsrslvr.dll" + ;-------------------------------- STRINGS ------------------------------- [Strings] Index: sdk/include/psdk/windns.h =================================================================== --- sdk/include/psdk/windns.h (revision 73120) +++ sdk/include/psdk/windns.h (working copy) @@ -549,6 +549,10 @@ DNS_STATUS WINAPI +DnsFlushResolverCache(); + +DNS_STATUS +WINAPI DnsAcquireContextHandle_A( _In_ DWORD CredentialFlags, _In_opt_ PVOID Credentials,