VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp@ 51441

Last change on this file since 51441 was 50263, checked in by vboxsync, 11 years ago

Main/HostDnsService:

  • Generic part could be used with threading on or off: OS which can monitor changes on DNS structures might need this (e.g. Windows, Darwin, Linux)
  • ResolvConf based (Linux, Solaris, FreeBSD ans Os/2) doesn't use scanf based resovl.conf parsing new Slirp's parser used instead. It's configured to provide strings instead of addresses. (to resolve xtracker/7034c2)
  • Darwin monitoring code has been refactored.
  • linux changed to handle cases described in xtracker/7034c3
  • Windows monitors changes on register changes.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.4 KB
Line 
1/* -*- indent-tabs-mode: nil; -*- */
2#include <VBox/com/string.h>
3#include <VBox/com/ptr.h>
4
5
6#include <iprt/assert.h>
7#include <iprt/err.h>
8
9#include <Windows.h>
10
11#include <string>
12#include <vector>
13#include "../HostDnsService.h"
14
15struct HostDnsServiceWin::Data
16{
17 HostDnsServiceWin::Data(){}
18 HKEY hKeyTcpipParameters;
19#define DATA_DNS_UPDATE_EVENT 0
20#define DATA_SHUTDOWN_EVENT 1
21#define DATA_MAX_EVENT 2
22 HANDLE haDataEvent[DATA_MAX_EVENT];
23};
24
25static inline int registerNotification(const HKEY& hKey, HANDLE& hEvent)
26{
27 LONG lrc = RegNotifyChangeKeyValue(hKey,
28 TRUE,
29 REG_NOTIFY_CHANGE_LAST_SET,
30 hEvent,
31 TRUE);
32 AssertMsgReturn(lrc == ERROR_SUCCESS,
33 ("Failed to register event on the key. Please debug me!"),
34 VERR_INTERNAL_ERROR);
35
36 return VINF_SUCCESS;
37}
38
39HostDnsServiceWin::HostDnsServiceWin():HostDnsMonitor(true), m(NULL)
40{
41 m = new Data();
42
43 m->haDataEvent[DATA_DNS_UPDATE_EVENT] = CreateEvent(NULL,
44 TRUE, FALSE, NULL);
45 AssertReleaseMsg(m->haDataEvent[DATA_DNS_UPDATE_EVENT],
46 ("Failed to create event for DNS event (%d)\n", GetLastError()));
47
48 m->haDataEvent[DATA_SHUTDOWN_EVENT] = CreateEvent(NULL,
49 TRUE, FALSE, NULL);
50 AssertReleaseMsg(m->haDataEvent[DATA_SHUTDOWN_EVENT],
51 ("Failed to create event for Shutdown signal (%d)\n", GetLastError()));
52
53 LONG lrc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
54 TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
55 0, KEY_READ|KEY_NOTIFY, &m->hKeyTcpipParameters);
56 AssertReleaseMsg(lrc == ERROR_SUCCESS,
57 ("Failed to open Registry Key for read and update notifications (%d)\n",
58 GetLastError()));
59}
60
61
62HostDnsServiceWin::~HostDnsServiceWin()
63{
64 if (m && !m->hKeyTcpipParameters)
65 {
66 RegCloseKey(m->hKeyTcpipParameters);
67 m->hKeyTcpipParameters = 0;
68
69 CloseHandle(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
70 CloseHandle(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
71
72 delete m;
73
74 m = NULL;
75 }
76}
77
78
79HRESULT HostDnsServiceWin::init()
80{
81 HRESULT hrc = HostDnsMonitor::init();
82 AssertComRCReturn(hrc, hrc);
83
84 return updateInfo();
85}
86
87
88void HostDnsServiceWin::monitorThreadShutdown()
89{
90 SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
91}
92
93
94int HostDnsServiceWin::monitorWorker()
95{
96 registerNotification(m->hKeyTcpipParameters,
97 m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
98
99 monitorThreadInitializationDone();
100
101 DWORD dwRc;
102 while (true)
103 {
104 dwRc = WaitForMultipleObjects(DATA_MAX_EVENT,
105 m->haDataEvent,
106 FALSE,
107 INFINITE);
108 AssertMsgReturn(dwRc != WAIT_FAILED,
109 ("WaitForMultipleObjects failed (%d) to wait! Please debug",
110 GetLastError()), VERR_INTERNAL_ERROR);
111
112 if ((dwRc - WAIT_OBJECT_0) == DATA_DNS_UPDATE_EVENT)
113 {
114 updateInfo();
115 notifyAll();
116 ResetEvent(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
117 registerNotification(m->hKeyTcpipParameters,
118 m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
119
120 }
121 else if ((dwRc - WAIT_OBJECT_0) == DATA_SHUTDOWN_EVENT)
122 {
123 break;
124 }
125 else
126 {
127 AssertMsgFailedReturn(
128 ("WaitForMultipleObjects returns out of bound index %d. Please debug!",
129 dwRc),
130 VERR_INTERNAL_ERROR);
131 }
132 }
133 return VINF_SUCCESS;
134}
135
136
137HRESULT HostDnsServiceWin::updateInfo()
138{
139 HRESULT hrc;
140 DWORD regIndex;
141 BYTE abDomain[256];
142 BYTE abNameServers[256];
143 BYTE abSearchList[256];
144
145 RT_ZERO(abDomain);
146 RT_ZERO(abNameServers);
147 RT_ZERO(abSearchList);
148
149 regIndex = 0;
150 do {
151 CHAR keyName[256];
152 DWORD cbKeyName = sizeof(keyName);
153 DWORD keyType = 0;
154 BYTE keyData[1024];
155 DWORD cbKeyData = sizeof(keyData);
156
157 hrc = RegEnumValueA(m->hKeyTcpipParameters, regIndex, keyName, &cbKeyName, 0,
158 &keyType, keyData, &cbKeyData);
159 if ( hrc == ERROR_SUCCESS
160 || hrc == ERROR_MORE_DATA)
161 {
162 if ( RTStrICmp("Domain", keyName) == 0
163 && cbKeyData > 1
164 && cbKeyData < sizeof(abDomain))
165 memcpy(abDomain, keyData, cbKeyData);
166
167 else if ( RTStrICmp("DhcpDomain", keyName) == 0
168 && cbKeyData > 1
169 && abDomain[0] == 0
170 && cbKeyData < sizeof(abDomain))
171 memcpy(abDomain, keyData, cbKeyData);
172
173 else if ( RTStrICmp("NameServer", keyName) == 0
174 && cbKeyData > 1
175 && cbKeyData < sizeof(abNameServers))
176 memcpy(abNameServers, keyData, cbKeyData);
177
178 else if ( RTStrICmp("DhcpNameServer", keyName) == 0
179 && cbKeyData > 1
180 && abNameServers[0] == 0
181 && cbKeyData < sizeof(abNameServers))
182 memcpy(abNameServers, keyData, cbKeyData);
183
184 else if ( RTStrICmp("SearchList", keyName) == 0
185 && cbKeyData > 1
186 && cbKeyData < sizeof(abSearchList))
187 memcpy(abSearchList, keyData, cbKeyData);
188 }
189 regIndex++;
190 } while (hrc != ERROR_NO_MORE_ITEMS);
191
192 /* OK, now parse and update DNS structures. */
193 /* domain name */
194 HostDnsInformation info;
195 info.domain = (char*)abDomain;
196
197 /* server list */
198 strList2List(info.servers, (char *)abNameServers);
199 /* search list */
200 strList2List(info.searchList, (char *)abSearchList);
201
202 HostDnsMonitor::setInfo(info);
203
204 return S_OK;
205}
206
207
208void HostDnsServiceWin::strList2List(std::vector<std::string>& lst, char *strLst)
209{
210 char *next, *current;
211 char address[512];
212
213 AssertPtrReturnVoid(strLst);
214
215 if (strlen(strLst) == 0)
216 return;
217
218 current = strLst;
219 do {
220 RT_ZERO(address);
221 next = RTStrStr(current, " ");
222
223 if (next)
224 strncpy(address, current, RT_MIN(sizeof(address)-1, next - current));
225 else
226 strcpy(address, current);
227
228 lst.push_back(std::string(address));
229
230 current = next + 1;
231 } while(next);
232
233}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette