https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d49d7b3282891359a11c7…
commit d49d7b3282891359a11c7ed553e8a31632c5d039
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Sun Oct 27 13:45:52 2019 +0100
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Sun Oct 27 13:48:04 2019 +0100
[DNSRSLVR] Add the DNS Resolver Cache Service
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
---
base/services/CMakeLists.txt | 1 +
base/services/dnsrslvr/CMakeLists.txt | 23 ++++
base/services/dnsrslvr/cache.c | 199 ++++++++++++++++++++++++++++++++++
base/services/dnsrslvr/dnsrslvr.c | 150 +++++++++++++++++++++++++
base/services/dnsrslvr/dnsrslvr.rc | 4 +
base/services/dnsrslvr/dnsrslvr.spec | 1 +
base/services/dnsrslvr/precomp.h | 45 ++++++++
base/services/dnsrslvr/rpcserver.c | 130 ++++++++++++++++++++++
media/inf/nettcpip.inf | 17 ++-
sdk/include/reactos/idl/dnsrslvr.idl | 3 +
sdk/include/reactos/windns_undoc.h | 6 +
11 files changed, 578 insertions(+), 1 deletion(-)
diff --git a/base/services/CMakeLists.txt b/base/services/CMakeLists.txt
index 62b5a90ccd9..2605101c793 100644
--- a/base/services/CMakeLists.txt
+++ b/base/services/CMakeLists.txt
@@ -2,6 +2,7 @@
add_subdirectory(audiosrv)
add_subdirectory(dcomlaunch)
add_subdirectory(dhcpcsvc)
+add_subdirectory(dnsrslvr)
add_subdirectory(eventlog)
add_subdirectory(netlogon)
add_subdirectory(nfsd)
diff --git a/base/services/dnsrslvr/CMakeLists.txt
b/base/services/dnsrslvr/CMakeLists.txt
new file mode 100644
index 00000000000..a2821d93763
--- /dev/null
+++ b/base/services/dnsrslvr/CMakeLists.txt
@@ -0,0 +1,23 @@
+
+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)
diff --git a/base/services/dnsrslvr/cache.c b/base/services/dnsrslvr/cache.c
new file mode 100644
index 00000000000..6a6eee4844e
--- /dev/null
+++ b/base/services/dnsrslvr/cache.c
@@ -0,0 +1,199 @@
+/*
+ * 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();
+}
diff --git a/base/services/dnsrslvr/dnsrslvr.c b/base/services/dnsrslvr/dnsrslvr.c
new file mode 100644
index 00000000000..c0384050ca9
--- /dev/null
+++ b/base/services/dnsrslvr/dnsrslvr.c
@@ -0,0 +1,150 @@
+/*
+ * 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 */
diff --git a/base/services/dnsrslvr/dnsrslvr.rc b/base/services/dnsrslvr/dnsrslvr.rc
new file mode 100644
index 00000000000..482aefe129f
--- /dev/null
+++ b/base/services/dnsrslvr/dnsrslvr.rc
@@ -0,0 +1,4 @@
+#define REACTOS_STR_FILE_DESCRIPTION "DNS-Client"
+#define REACTOS_STR_INTERNAL_NAME "dnsrslvr"
+#define REACTOS_STR_ORIGINAL_FILENAME "dnsrslvr.dll"
+#include <reactos/version.rc>
diff --git a/base/services/dnsrslvr/dnsrslvr.spec b/base/services/dnsrslvr/dnsrslvr.spec
new file mode 100644
index 00000000000..1b27fe53864
--- /dev/null
+++ b/base/services/dnsrslvr/dnsrslvr.spec
@@ -0,0 +1 @@
+@ stdcall ServiceMain(long ptr)
diff --git a/base/services/dnsrslvr/precomp.h b/base/services/dnsrslvr/precomp.h
new file mode 100644
index 00000000000..0a11db5ee62
--- /dev/null
+++ b/base/services/dnsrslvr/precomp.h
@@ -0,0 +1,45 @@
+#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_ */
diff --git a/base/services/dnsrslvr/rpcserver.c b/base/services/dnsrslvr/rpcserver.c
new file mode 100644
index 00000000000..0cb5c1f8b59
--- /dev/null
+++ b/base/services/dnsrslvr/rpcserver.c
@@ -0,0 +1,130 @@
+/*
+ * 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)
+{
+}
diff --git a/media/inf/nettcpip.inf b/media/inf/nettcpip.inf
index eaf1b7cc9eb..d179e9d0499 100644
--- a/media/inf/nettcpip.inf
+++ b/media/inf/nettcpip.inf
@@ -27,7 +27,7 @@ AddReg = TCPIP_AddReg_Global.NT
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
@@ -236,6 +236,7 @@
HKLM,"SYSTEM\CurrentControlSet\Services\Winsock2\Parameters\Protocol_Catalog9\Ca
[MS_TCPIP.PrimaryInstall.Services]
AddService = Tcpip, , tcpip_Service_Inst
AddService = DHCP, , dhcp_Service_Inst
+AddService = Dnscache, , dns_Service_Inst
[tcpip_Service_Inst]
ServiceType = 1
@@ -275,6 +276,20 @@ AddReg=dhcp_AddReg
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]
diff --git a/sdk/include/reactos/idl/dnsrslvr.idl b/sdk/include/reactos/idl/dnsrslvr.idl
index ee5af553fb5..787e5c71267 100644
--- a/sdk/include/reactos/idl/dnsrslvr.idl
+++ b/sdk/include/reactos/idl/dnsrslvr.idl
@@ -6,7 +6,10 @@
#define UNICODE
#include <sal.h>
+
+cpp_quote("#ifndef _WINDNS_INCLUDED_")
#include <windns.h>
+cpp_quote("#endif")
typedef [handle, string] LPWSTR DNSRSLVR_HANDLE;
diff --git a/sdk/include/reactos/windns_undoc.h b/sdk/include/reactos/windns_undoc.h
index 3af80a1dfc5..01e6f412095 100644
--- a/sdk/include/reactos/windns_undoc.h
+++ b/sdk/include/reactos/windns_undoc.h
@@ -14,6 +14,10 @@ typedef struct _DNS_CACHE_ENTRY
unsigned short wFlags; /* DNS Record Flags */
} DNS_CACHE_ENTRY, *PDNS_CACHE_ENTRY;
+
+#ifndef __WIDL__
+// Hack
+
BOOL
WINAPI
DnsFlushResolverCache(VOID);
@@ -23,6 +27,8 @@ WINAPI
DnsGetCacheDataTable(
_Out_ PDNS_CACHE_ENTRY *DnsCache);
+#endif /* __WIDL__ */
+
#ifdef __cplusplus
}
#endif