Patch written by Peter Hater and Christoph von Wittich.
Slightly modified by me in order to
- fix bit-rot
- fix header include issues
- disable integration with dnsapi because of confusing use of DnsQweryEx().
Integration with dnsapi will follow in a future commit.
CORE-12159
add_subdirectory(audiosrv)
add_subdirectory(dcomlaunch)
add_subdirectory(dhcpcsvc)
+add_subdirectory(dnsrslvr)
add_subdirectory(eventlog)
add_subdirectory(netlogon)
add_subdirectory(nfsd)
--- /dev/null
+
+include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl)
+add_rpc_files(server ${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl/dnsrslvr.idl)
+
+list(APPEND SOURCE
+ cache.c
+ dnsrslvr.c
+ rpcserver.c
+ precomp.h
+ ${CMAKE_CURRENT_BINARY_DIR}/dnsrslvr_s.c)
+
+spec2def(dnsrslvr.dll dnsrslvr.spec ADD_IMPORTLIB)
+
+add_library(dnsrslvr SHARED ${SOURCE} dnsrslvr.rc ${CMAKE_CURRENT_BINARY_DIR}/dnsrslvr.def)
+
+if(NOT MSVC)
+ target_link_libraries(dnsrslvr ${PSEH_LIB})
+endif()
+
+set_module_type(dnsrslvr win32dll UNICODE)
+add_importlibs(dnsrslvr advapi32 rpcrt4 dnsapi iphlpapi msvcrt kernel32 ntdll)
+add_pch(dnsrslvr precomp.h SOURCE)
+add_cd_file(TARGET dnsrslvr DESTINATION reactos/system32 FOR all)
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS system libraries
+ * FILE: base/services/dnsrslvr/cache.c
+ * PURPOSE: DNS cache functions
+ * PROGRAMMER: Peter Hater
+ */
+
+#include "precomp.h"
+
+//#define NDEBUG
+#include <debug.h>
+
+static RESOLVER_CACHE DnsCache;
+static BOOL DnsCacheInitialized = FALSE;
+
+#define DnsCacheLock() do { EnterCriticalSection(&DnsCache.Lock); } while (0)
+#define DnsCacheUnlock() do { LeaveCriticalSection(&DnsCache.Lock); } while (0)
+
+VOID
+DnsIntCacheInitialize(VOID)
+{
+ DPRINT("DnsIntCacheInitialize\n");
+
+ /* Check if we're initialized */
+ if (DnsCacheInitialized)
+ return;
+
+ /* Initialize the cache lock and namespace list */
+ InitializeCriticalSection((LPCRITICAL_SECTION)&DnsCache.Lock);
+ InitializeListHead(&DnsCache.RecordList);
+ DnsCacheInitialized = TRUE;
+}
+
+VOID
+DnsIntCacheFree(VOID)
+{
+ DPRINT("DnsIntCacheFree\n");
+
+ /* Check if we're initialized */
+ if (!DnsCacheInitialized)
+ return;
+
+ if (!DnsCache.RecordList.Flink)
+ return;
+
+ DnsIntCacheFlush();
+
+ DeleteCriticalSection(&DnsCache.Lock);
+ DnsCacheInitialized = FALSE;
+}
+
+VOID
+DnsIntCacheRemoveEntryItem(PRESOLVER_CACHE_ENTRY CacheEntry)
+{
+ DPRINT("DnsIntCacheRemoveEntryItem %p\n", CacheEntry);
+
+ /* Remove the entry from the list */
+ RemoveEntryList(&CacheEntry->CacheLink);
+
+ /* Free record */
+ DnsRecordListFree(CacheEntry->Record, DnsFreeRecordList);
+
+ /* Delete us */
+ HeapFree(GetProcessHeap(), 0, CacheEntry);
+}
+
+VOID
+DnsIntCacheFlush(VOID)
+{
+ PLIST_ENTRY Entry;
+ PRESOLVER_CACHE_ENTRY CacheEntry;
+
+ DPRINT("DnsIntCacheFlush\n");
+
+ /* Lock the cache */
+ DnsCacheLock();
+
+ /* Loop every entry */
+ Entry = DnsCache.RecordList.Flink;
+ while (Entry != &DnsCache.RecordList)
+ {
+ /* Get this entry */
+ CacheEntry = CONTAINING_RECORD(Entry, RESOLVER_CACHE_ENTRY, CacheLink);
+
+ /* Remove it from list */
+ DnsIntCacheRemoveEntryItem(CacheEntry);
+
+ /* Move to the next entry */
+ Entry = DnsCache.RecordList.Flink;
+ }
+
+ /* Unlock the cache */
+ DnsCacheUnlock();
+}
+
+BOOL
+DnsIntCacheGetEntryFromName(LPCWSTR Name,
+ PDNS_RECORDW *Record)
+{
+ BOOL Ret = FALSE;
+ PRESOLVER_CACHE_ENTRY CacheEntry;
+ PLIST_ENTRY NextEntry;
+
+ DPRINT("DnsIntCacheGetEntryFromName %ws %p\n", Name, Record);
+
+ /* Assume failure */
+ *Record = NULL;
+
+ /* Lock the cache */
+ DnsCacheLock();
+
+ /* Match the Id with all the entries in the List */
+ NextEntry = DnsCache.RecordList.Flink;
+ while (NextEntry != &DnsCache.RecordList)
+ {
+ /* Get the Current Entry */
+ CacheEntry = CONTAINING_RECORD(NextEntry, RESOLVER_CACHE_ENTRY, CacheLink);
+
+ /* Check if this is the Catalog Entry ID we want */
+ if (_wcsicmp(CacheEntry->Record->pName, Name) == 0)
+ {
+ /* Copy the entry and return it */
+ *Record = DnsRecordSetCopyEx(CacheEntry->Record, DnsCharSetUnicode, DnsCharSetUnicode);
+ Ret = TRUE;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Release the cache */
+ DnsCacheUnlock();
+
+ /* Return */
+ return Ret;
+}
+
+BOOL
+DnsIntCacheRemoveEntryByName(LPCWSTR Name)
+{
+ BOOL Ret = FALSE;
+ PRESOLVER_CACHE_ENTRY CacheEntry;
+ PLIST_ENTRY NextEntry;
+
+ DPRINT("DnsIntCacheRemoveEntryByName %ws\n", Name);
+
+ /* Lock the cache */
+ DnsCacheLock();
+
+ /* Match the Id with all the entries in the List */
+ NextEntry = DnsCache.RecordList.Flink;
+ while (NextEntry != &DnsCache.RecordList)
+ {
+ /* Get the Current Entry */
+ CacheEntry = CONTAINING_RECORD(NextEntry, RESOLVER_CACHE_ENTRY, CacheLink);
+
+ /* Check if this is the Catalog Entry ID we want */
+ if (_wcsicmp(CacheEntry->Record->pName, Name) == 0)
+ {
+ /* Remove the entry */
+ DnsIntCacheRemoveEntryItem(CacheEntry);
+ Ret = TRUE;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Release the cache */
+ DnsCacheUnlock();
+
+ /* Return */
+ return Ret;
+}
+
+VOID
+DnsIntCacheAddEntry(PDNS_RECORDW Record)
+{
+ PRESOLVER_CACHE_ENTRY Entry;
+
+ DPRINT("DnsIntCacheRemoveEntryByName %p\n", Record);
+
+ /* Lock the cache */
+ DnsCacheLock();
+
+ /* Match the Id with all the entries in the List */
+ Entry = (PRESOLVER_CACHE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(*Entry));
+ if (!Entry)
+ return;
+
+ Entry->Record = DnsRecordSetCopyEx(Record, DnsCharSetUnicode, DnsCharSetUnicode);
+
+ /* Insert it to our List */
+ InsertTailList(&DnsCache.RecordList, &Entry->CacheLink);
+
+ /* Release the cache */
+ DnsCacheUnlock();
+}
--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS DNS Resolver
+ * FILE: base/services/dnsrslvr/dnsrslvr.c
+ * PURPOSE: DNS Resolver Service
+ * PROGRAMMER: Christoph von Wittich
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include "precomp.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ******************************************************************/
+
+HINSTANCE hDllInstance;
+SERVICE_STATUS_HANDLE ServiceStatusHandle;
+SERVICE_STATUS SvcStatus;
+static WCHAR ServiceName[] = L"Dnscache";
+
+DWORD WINAPI RpcThreadRoutine(LPVOID lpParameter);
+
+/* FUNCTIONS *****************************************************************/
+
+static
+VOID
+UpdateServiceStatus(
+ HANDLE hServiceStatus,
+ DWORD NewStatus,
+ DWORD Increment)
+{
+ if (Increment > 0)
+ SvcStatus.dwCheckPoint += Increment;
+ else
+ SvcStatus.dwCheckPoint = 0;
+
+ SvcStatus.dwCurrentState = NewStatus;
+ SetServiceStatus(hServiceStatus, &SvcStatus);
+}
+
+static
+DWORD
+WINAPI
+ServiceControlHandler(
+ DWORD dwControl,
+ DWORD dwEventType,
+ LPVOID lpEventData,
+ LPVOID lpContext)
+{
+ switch (dwControl)
+ {
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ UpdateServiceStatus(ServiceStatusHandle, SERVICE_STOP_PENDING, 1);
+ RpcMgmtStopServerListening(NULL);
+ DnsIntCacheFree();
+ UpdateServiceStatus(ServiceStatusHandle, SERVICE_STOPPED, 0);
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ return NO_ERROR;
+
+ default:
+ return ERROR_CALL_NOT_IMPLEMENTED;
+ }
+ return NO_ERROR;
+}
+
+VOID
+WINAPI
+ServiceMain(
+ DWORD argc,
+ LPWSTR *argv)
+{
+ HANDLE hThread;
+
+ UNREFERENCED_PARAMETER(argc);
+ UNREFERENCED_PARAMETER(argv);
+
+ DPRINT("ServiceMain() called\n");
+
+ SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ SvcStatus.dwCurrentState = SERVICE_START_PENDING;
+ SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+ SvcStatus.dwCheckPoint = 0;
+ SvcStatus.dwWin32ExitCode = NO_ERROR;
+ SvcStatus.dwServiceSpecificExitCode = 0;
+ SvcStatus.dwWaitHint = 4000;
+
+ ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
+ ServiceControlHandler,
+ NULL);
+
+ if (!ServiceStatusHandle)
+ {
+ DPRINT1("DNSRSLVR: Unable to register service control handler (%lx)\n", GetLastError());
+ return; // FALSE
+ }
+
+ DnsIntCacheInitialize();
+
+ hThread = CreateThread(NULL,
+ 0,
+ (LPTHREAD_START_ROUTINE)
+ RpcThreadRoutine,
+ NULL,
+ 0,
+ NULL);
+
+ if (!hThread)
+ {
+ DnsIntCacheFree();
+ DPRINT("Can't create RpcThread\n");
+ UpdateServiceStatus(ServiceStatusHandle, SERVICE_STOPPED, 0);
+ }
+ else
+ {
+ CloseHandle(hThread);
+ }
+
+ DPRINT("ServiceMain() done\n");
+ UpdateServiceStatus(ServiceStatusHandle, SERVICE_RUNNING, 0);
+}
+
+BOOL
+WINAPI
+DllMain(
+ _In_ HINSTANCE hinstDLL,
+ _In_ DWORD fdwReason,
+ _In_ PVOID pvReserved)
+{
+ UNREFERENCED_PARAMETER(pvReserved);
+
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstDLL);
+ hDllInstance = hinstDLL;
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+/* EOF */
--- /dev/null
+#define REACTOS_STR_FILE_DESCRIPTION "DNS-Client"
+#define REACTOS_STR_INTERNAL_NAME "dnsrslvr"
+#define REACTOS_STR_ORIGINAL_FILENAME "dnsrslvr.dll"
+#include <reactos/version.rc>
--- /dev/null
+@ stdcall ServiceMain(long ptr)
--- /dev/null
+#ifndef _DNSRSLVR_PCH_
+#define _DNSRSLVR_PCH_
+
+#include <stdarg.h>
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
+#include <windef.h>
+#include <winbase.h>
+#include <winsvc.h>
+#include <windns.h>
+
+#include <ndk/rtlfuncs.h>
+#include <ndk/obfuncs.h>
+
+#include <dnsrslvr_s.h>
+
+typedef struct _RESOLVER_CACHE_ENTRY
+{
+ LIST_ENTRY CacheLink;
+ PDNS_RECORDW Record;
+} RESOLVER_CACHE_ENTRY, *PRESOLVER_CACHE_ENTRY;
+
+typedef struct _RESOLVER_CACHE
+{
+ LIST_ENTRY RecordList;
+ CRITICAL_SECTION Lock;
+} RESOLVER_CACHE, *PRESOLVER_CACHE;
+
+
+/* cache.c */
+
+VOID DnsIntCacheInitialize(VOID);
+VOID DnsIntCacheRemoveEntryItem(PRESOLVER_CACHE_ENTRY CacheEntry);
+VOID DnsIntCacheFree(VOID);
+VOID DnsIntCacheFlush(VOID);
+BOOL DnsIntCacheGetEntryFromName(LPCWSTR Name,
+ PDNS_RECORDW *Record);
+VOID DnsIntCacheAddEntry(PDNS_RECORDW Record);
+BOOL DnsIntCacheRemoveEntryByName(LPCWSTR Name);
+
+
+#endif /* _DNSRSLVR_PCH_ */
--- /dev/null
+/*
+ * PROJECT: ReactOS DNS Resolver
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: base/services/dnsrslvr/rpcserver.c
+ * PURPOSE: RPC server interface
+ * COPYRIGHT: Copyright 2016 Christoph von Wittich
+ */
+
+#include "precomp.h"
+
+#define NDEBUG
+#include <debug.h>
+
+DWORD
+WINAPI
+RpcThreadRoutine(LPVOID lpParameter)
+{
+ RPC_STATUS Status;
+
+ Status = RpcServerUseProtseqEpW(L"ncalrpc", 20, L"DNSResolver", NULL);
+ if (Status != RPC_S_OK)
+ {
+ DPRINT("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
+ return 0;
+ }
+
+ Status = RpcServerRegisterIf(DnsResolver_v2_0_s_ifspec, NULL, NULL);
+ if (Status != RPC_S_OK)
+ {
+ DPRINT("RpcServerRegisterIf() failed (Status %lx)\n", Status);
+ return 0;
+ }
+
+ Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, 0);
+ if (Status != RPC_S_OK)
+ {
+ DPRINT("RpcServerListen() failed (Status %lx)\n", Status);
+ }
+
+ DPRINT("RpcServerListen finished\n");
+ return 0;
+}
+
+DWORD
+R_ResolverFlushCache(
+ DNSRSLVR_HANDLE pwszServerName)
+{
+ // FIXME Should store (and flush) entries by server handle
+ DnsIntCacheFlush();
+ return 0;
+}
+
+DWORD
+R_ResolverQuery(
+ DNSRSLVR_HANDLE pwszServerName,
+ LPCWSTR pwsName,
+ WORD wType,
+ DWORD Flags,
+ DWORD *dwRecords,
+ DNS_RECORDW **ppResultRecords)
+{
+#if 0
+ DNS_QUERY_REQUEST QueryRequest = { 0 };
+ DNS_QUERY_RESULT QueryResults = { 0 };
+#endif
+ DNS_STATUS Status;
+ PDNS_RECORDW Record;
+
+ DPRINT1("R_ResolverQuery %p %p %x %lx %p %p\n",
+ pwszServerName, pwsName, wType, Flags, dwRecords, ppResultRecords);
+
+ if (!pwszServerName || !pwsName || !wType || !ppResultRecords)
+ return ERROR_INVALID_PARAMETER;
+
+ // FIXME Should lookup entries by server handle
+ if (DnsIntCacheGetEntryFromName(pwsName, ppResultRecords))
+ {
+ Status = ERROR_SUCCESS;
+ }
+ else
+ {
+#if 0
+ QueryRequest.Version = DNS_QUERY_REQUEST_VERSION1;
+ QueryRequest.QueryType = wType;
+ QueryRequest.QueryName = pwsName;
+ QueryRequest.QueryOptions = Flags;
+ QueryResults.Version = DNS_QUERY_REQUEST_VERSION1;
+
+ Status = DnsQueryEx(&QueryRequest, &QueryResults, NULL);
+ if (Status == ERROR_SUCCESS)
+ {
+ // FIXME Should store (and flush) entries by server handle
+ DnsIntCacheAddEntry(QueryResults.pQueryRecords);
+ *ppResultRecords = QueryResults.pQueryRecords;
+ }
+#endif
+ }
+
+ if (dwRecords)
+ *dwRecords = 0;
+
+ if (Status == ERROR_SUCCESS)
+ {
+ Record = *ppResultRecords;
+ while (Record)
+ {
+ if (dwRecords)
+ (*dwRecords)++;
+ Record = Record->pNext;
+ }
+ }
+
+ DPRINT1("R_ResolverQuery result %ld %ld\n", Status, *dwRecords);
+
+ return Status;
+}
+
+void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
+{
+ return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+}
+
+void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
+{
+ HeapFree(GetProcessHeap(), 0, ptr);
+}
+
+void __RPC_USER WLANSVC_RPC_HANDLE_rundown(DNSRSLVR_HANDLE hClientHandle)
+{
+}
HKR,"Ndi","ClsId",0x00000000,"{A907657F-6FDF-11D0-8EFB-00C04FD912B2}"
HKR,"Ndi","HelpText",0x00000000,"Transmission Control Protocol/Internet Protocol"
HKR,"Ndi","Service",0x00000000,"Tcpip"
-HKR,"Ndi","CoServices",0x00010000,"Tcpip","Dhcp"
+HKR,"Ndi","CoServices",0x00010000,"Tcpip","Dhcp","Dnscache"
; TCP/IPv4 driver
; NOTE: These settings should be added by the network setup
[MS_TCPIP.PrimaryInstall.Services]
AddService = Tcpip, , tcpip_Service_Inst
AddService = DHCP, , dhcp_Service_Inst
+AddService = Dnscache, , dns_Service_Inst
[tcpip_Service_Inst]
ServiceType = 1
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]
#define UNICODE
#include <sal.h>
+
+cpp_quote("#ifndef _WINDNS_INCLUDED_")
#include <windns.h>
+cpp_quote("#endif")
typedef [handle, string] LPWSTR DNSRSLVR_HANDLE;
unsigned short wFlags; /* DNS Record Flags */
} DNS_CACHE_ENTRY, *PDNS_CACHE_ENTRY;
+
+#ifndef __WIDL__
+// Hack
+
BOOL
WINAPI
DnsFlushResolverCache(VOID);
DnsGetCacheDataTable(
_Out_ PDNS_CACHE_ENTRY *DnsCache);
+#endif /* __WIDL__ */
+
#ifdef __cplusplus
}
#endif