Changeset 52897 in vbox for trunk/src/VBox/Main/src-server/win
- Timestamp:
- Sep 30, 2014 2:45:00 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp
r50263 r52897 1 /* -*- indent-tabs-mode: nil; -*- */ 1 /* $Id$ */ 2 /** @file 3 * Host DNS listener for Windows. 4 */ 5 6 /* 7 * Copyright (C) 2014 Oracle Corporation 8 * 9 * This file is part of VirtualBox Open Source Edition (OSE), as 10 * available from http://www.virtualbox.org. This file is free software; 11 * you can redistribute it and/or modify it under the terms of the GNU 12 * General Public License (GPL) as published by the Free Software 13 * Foundation, in version 2 as it comes in the "COPYING" file of the 14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 */ 17 2 18 #include <VBox/com/string.h> 3 19 #include <VBox/com/ptr.h> 4 20 #include <VBox/log.h> 5 21 6 22 #include <iprt/assert.h> … … 10 26 11 27 #include <string> 28 #include <sstream> 12 29 #include <vector> 13 30 #include "../HostDnsService.h" 14 31 15 struct 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 25 static 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 39 HostDnsServiceWin::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())); 32 /* In order to monitor DNS setting updates we need to receive notification about 33 * Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\* keys changes. 34 * Since it is not possible to use patterns when subscribing key changes, we need to find valid paths for all such 35 * keys manually and subscribe to changes one by one (see enumerateSubTree()). */ 36 const TCHAR HostDnsServiceWin::m_pwcKeyRoot[] = _T("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"); 37 38 39 HostDnsServiceWin::HostDnsServiceWin() 40 : HostDnsMonitor(true), 41 m_aWarehouse(), 42 m_hostInfoCache(), 43 m_fInitialized(false) 44 { 45 /* Add monitor destroy event. 46 * This event should have index '0' at the events array in order to separate it from 47 * DNS and tree change events. When this event occurs all resources should be released. */ 48 if (subscribeTo(NULL, NULL, 0)) 49 { 50 /* Add registry tree change event and corresponding key. 51 * This event should have index '1' at the events array in order to separate it from DNS events. 52 * When this event occurs it means there are changes in the list of available network interfaces. 53 * Network interfaces should be re-enumerated, all DNS events and keys data should re-initialized. */ 54 if (subscribeTo(const_cast<TCHAR *>(m_pwcKeyRoot), NULL, REG_NOTIFY_CHANGE_NAME)) 55 { 56 /* Enumerate all available network interfaces, create events and corresponding keys and perform subscription. */ 57 if (enumerateSubTree()) 58 { 59 updateInfo(NULL); 60 m_fInitialized = true; 61 return; 62 } 63 else 64 LogRel(("WARNING: cannot set up monitor properly (3); monitor now disabled.\n")); 65 } 66 else 67 /* Too bad we can't even subscribe to notifications about network interfaces changes. */ 68 LogRel(("WARNING: cannot set up monitor properly (2); monitor now disabled.\n")); 69 } 70 else 71 /* Too bad we can't even subscribe to destroy event. */ 72 LogRel(("WARNING: cannot set up monitor properly (1); monitor now disabled.\n")); 73 74 releaseResources(); 59 75 } 60 76 … … 62 78 HostDnsServiceWin::~HostDnsServiceWin() 63 79 { 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 } 80 monitorThreadShutdown(); 81 releaseResources(); 82 m_fInitialized = false; 83 } 84 85 86 bool HostDnsServiceWin::releaseWarehouseItem(int idxItem) 87 { 88 bool rc = true; 89 /* We do not check if idxItem is in valid range of m_aWarehouse here 90 * (a bit of performance optimization), so make sure you provided a valid value! */ 91 struct Item oTmpItem = m_aWarehouse[idxItem]; 92 93 /* Non-zero return code means ResetEvent() succeeded. */ 94 rc = ResetEvent(oTmpItem.hEvent) != 0; 95 if (!rc) LogRel(("Failed to reset event (idxItem=%d); monitor unstable (rc=%d).\n", idxItem, GetLastError())); 96 CloseHandle(oTmpItem.hEvent); 97 oTmpItem.hEvent = NULL; 98 99 RegCloseKey(oTmpItem.hKey); 100 oTmpItem.hKey = NULL; 101 102 Log2(("Unsubscribed from %ls notifications\n", oTmpItem.wcsInterface)); 103 104 m_aWarehouse.erase(m_aWarehouse.begin() + idxItem); 105 106 return rc; 107 } 108 109 110 bool HostDnsServiceWin::dropSubTreeNotifications() 111 { 112 bool rc = true; 113 /* Any sub-tree events we subscribed? */ 114 if (m_aWarehouse.size() > VBOX_OFFSET_SUBTREE_EVENTS) 115 /* Going from the end to the beginning. */ 116 for (int idxItem = (int)m_aWarehouse.size() - 1; idxItem >= VBOX_OFFSET_SUBTREE_EVENTS; idxItem--) 117 rc &= releaseWarehouseItem(idxItem); 118 119 size_t cElementsLeft = m_aWarehouse.size(); 120 if (cElementsLeft != VBOX_OFFSET_SUBTREE_EVENTS) 121 { 122 LogRel(("DNS monitor unstable; %d events left after dropping.\n", (int)cElementsLeft - VBOX_OFFSET_SUBTREE_EVENTS)); 123 return false; 124 } 125 126 return rc; 127 } 128 129 130 void HostDnsServiceWin::releaseResources() 131 { 132 /* First, drop notifications subscription for sub-tree keys. */ 133 dropSubTreeNotifications(); 134 135 /* Then release notification about tree structure changes. */ 136 if (m_aWarehouse.size() > VBOX_OFFSET_TREE_EVENT) 137 releaseWarehouseItem(VBOX_OFFSET_TREE_EVENT); 138 139 /* Release shutdown event. */ 140 if (m_aWarehouse.size() > VBOX_OFFSET_SHUTDOWN_EVENT) 141 releaseWarehouseItem(VBOX_OFFSET_SHUTDOWN_EVENT); 142 143 AssertReturnVoid(m_aWarehouse.size() == 0); 144 } 145 146 147 bool HostDnsServiceWin::subscribeTo(TCHAR *wcsPath, TCHAR *wcsInterface, DWORD fFilter) 148 { 149 HKEY hTmpKey = NULL; 150 HANDLE hTmpEvent = NULL; 151 152 /* Do not add more than MAXIMUM_WAIT_OBJECTS items to the array due to WaitForMultipleObjects() limitation. */ 153 if ((m_aWarehouse.size() + 1 /* the array size if we would add an extra item */ ) > MAXIMUM_WAIT_OBJECTS) 154 { 155 LogRel(("Too many items to monitor.\n")); 156 return false; 157 } 158 159 hTmpEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 160 if (!hTmpEvent) 161 return false; 162 163 /* wcsPath might not be specified if we want to subscribe to the termination event. In this case 164 * it is assumed that this is the first issued subscription request (i.e., m_aWarehouse.size() == 0). */ 165 if (wcsPath) 166 { 167 LONG rc; 168 /* Open registry key itself. */ 169 rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wcsPath, 0, KEY_READ | KEY_NOTIFY, &hTmpKey); 170 if (rc == ERROR_SUCCESS) 171 { 172 /* Link registry key and notification event. */ 173 rc = RegNotifyChangeKeyValue(hTmpKey, TRUE, fFilter, hTmpEvent, TRUE); 174 if (rc != ERROR_SUCCESS) 175 { 176 /* Don't leak! */ 177 RegCloseKey(hTmpKey); 178 LogRel(("Unable to register key notification (rc=0x%X).\n", rc)); 179 } 180 } 181 else 182 LogRel(("Unable to open key (rc=0x%X)\n", rc)); 183 184 /* All good so far? */ 185 if (rc != ERROR_SUCCESS) 186 { 187 LogRel(("WARNING: unable to set up %ls registry key notifications.\n", wcsPath)); 188 CloseHandle(hTmpEvent); 189 return false; 190 } 191 } 192 else if (m_aWarehouse.size() > 0) 193 { 194 LogRel(("Subscription to termination event already established.\n")); 195 CloseHandle(hTmpEvent); 196 return false; 197 } 198 199 /* Finally, construct array item and queue it. */ 200 struct Item oTmpItem = { hTmpKey, hTmpEvent, NULL }; 201 202 /* Sub-tree keys should provide interface name (UUID). This is needed in order to 203 * collect all useful network settings to HostDnsInformation storage object to provide it to parent class. */ 204 if (wcsInterface) 205 _tcscpy(oTmpItem.wcsInterface, wcsInterface); 206 207 if (wcsPath) 208 Log2(("Subscription to %ls established.\n", wcsPath)); 209 210 m_aWarehouse.push_back(oTmpItem); 211 212 return true; 213 } 214 215 216 bool HostDnsServiceWin::enumerateSubTree() 217 { 218 LONG rc = 0; 219 HKEY hTmpKey; 220 DWORD cSubKeys = 0; 221 DWORD cbSubKeyNameMax = 0; 222 223 /* Enumerate all the available interfaces. */ 224 rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, m_pwcKeyRoot, 0, KEY_READ, &hTmpKey); 225 if (rc == ERROR_SUCCESS) 226 { 227 /* Get info about amount of available network interfaces. */ 228 rc = RegQueryInfoKey(hTmpKey, NULL, NULL, NULL, &cSubKeys, &cbSubKeyNameMax, NULL, NULL, NULL, NULL, NULL, NULL); 229 if (rc == ERROR_SUCCESS) 230 { 231 /* Now iterate over interfaces if: 232 * 1) there are interfaces available and 233 * 2) maximum length of an interface name conforms to our buffer allocation size. */ 234 if (cSubKeys > 0 && cbSubKeyNameMax <= VBOX_KEY_NAME_LEN_MAX) 235 { 236 TCHAR sSubKeyName[VBOX_KEY_NAME_LEN_MAX]; 237 for (DWORD idxSubKey = 0; idxSubKey < cSubKeys; idxSubKey++) 238 { 239 rc = RegEnumKey(hTmpKey, idxSubKey, sSubKeyName, VBOX_KEY_NAME_LEN_MAX); 240 if (rc == ERROR_SUCCESS) 241 { 242 /* Since we already know interface name (actually UUID), construct full registry path here. */ 243 TCHAR sSubKeyFullPath[VBOX_KEY_NAME_LEN_MAX]; 244 RT_ZERO(sSubKeyFullPath); 245 _tcscpy(sSubKeyFullPath, m_pwcKeyRoot); 246 rc = _tcscat_s(sSubKeyFullPath, VBOX_KEY_NAME_LEN_MAX, _T("\\")); 247 rc |= _tcscat_s(sSubKeyFullPath, VBOX_KEY_NAME_LEN_MAX, sSubKeyName); 248 if (rc == 0) 249 subscribeTo(sSubKeyFullPath, sSubKeyName, REG_NOTIFY_CHANGE_LAST_SET); 250 } 251 else 252 LogRel(("Unable to open interfaces list (1).\n")); 253 } 254 RegCloseKey(hTmpKey); 255 return true; 256 } 257 else 258 LogRel(("Unable to open interfaces list (2).\n")); 259 } 260 else 261 LogRel(("Unable to open interfaces list (3).\n")); 262 RegCloseKey(hTmpKey); 263 } 264 else 265 LogRel(("Unable to open interfaces list (4).\n")); 266 return false; 76 267 } 77 268 … … 82 273 AssertComRCReturn(hrc, hrc); 83 274 84 return updateInfo( );275 return updateInfo(NULL); 85 276 } 86 277 … … 88 279 void HostDnsServiceWin::monitorThreadShutdown() 89 280 { 90 SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]); 281 AssertReturnVoid(m_aWarehouse.size() > VBOX_OFFSET_SHUTDOWN_EVENT); 282 SetEvent(m_aWarehouse[VBOX_OFFSET_SHUTDOWN_EVENT].hEvent); 283 } 284 285 286 void HostDnsServiceWin::extendVectorWithStrings(std::vector<std::wstring>& pVectorToExtend, std::wstring &wcsParameter) 287 { 288 std::wstringstream wcsStream(wcsParameter); 289 std::wstring wcsSubString; 290 291 while (std::getline(wcsStream, wcsSubString, _T(' '))) 292 pVectorToExtend.push_back(wcsSubString); 293 } 294 295 296 #ifdef DEBUG 297 static void hostDnsWinDumpList(std::vector<std::wstring>& awcszValues) 298 { 299 for (int idxItem = 0; idxItem < awcszValues.size(); idxItem++) 300 { 301 LogRel(("%ls\n", awcszValues[idxItem].data())); 302 } 303 } 304 #endif /* DEBUG */ 305 306 307 HRESULT HostDnsServiceWin::updateInfo(uint8_t *fWhatsChanged) 308 { 309 HostDnsInformation pHostDnsInfo; 310 RT_ZERO(pHostDnsInfo); 311 312 /* Any interfaces available? */ 313 if (m_aWarehouse.size() > VBOX_OFFSET_SUBTREE_EVENTS) 314 { 315 /* Walk across all the available interfaces and collect network configuration data: 316 * domain name, name servers and search list. */ 317 for (int idxKey = VBOX_OFFSET_SUBTREE_EVENTS; idxKey < m_aWarehouse.size(); idxKey++) 318 { 319 LONG rc; 320 321 /* Get number of key values. */ 322 DWORD cValues = 0; 323 rc = RegQueryInfoKey(m_aWarehouse[idxKey].hKey, NULL, NULL, NULL, NULL, NULL, NULL, &cValues, NULL, NULL, NULL, NULL); 324 if (rc == ERROR_SUCCESS) 325 { 326 for (DWORD idxValue = 0; idxValue < cValues; idxValue++) 327 { 328 TCHAR wcsValueName[VBOX_KEY_NAME_LEN_MAX]; 329 DWORD cbValueName = VBOX_KEY_NAME_LEN_MAX; 330 TCHAR wcsData[VBOX_KEY_NAME_LEN_MAX]; 331 DWORD cbData = VBOX_KEY_NAME_LEN_MAX; 332 333 /* Walk across all the properties of given interface. */ 334 rc = RegEnumValue(m_aWarehouse[idxKey].hKey, idxValue, wcsValueName, &cbValueName, 0, NULL, (LPBYTE)wcsData, &cbData); 335 if (rc == ERROR_SUCCESS) 336 { 337 338 if (( _tcscmp(wcsValueName, _T("Domain")) == 0 339 || _tcscmp(wcsValueName, _T("DhcpDomain")) == 0) 340 && _tcslen(wcsData) > 0) 341 { 342 /* We rely on that fact that Windows host cannot be a member of more than one domain in the same time! */ 343 if (pHostDnsInfo.domain.empty()) 344 pHostDnsInfo.domain = std::wstring(wcsData); 345 } 346 else if (( _tcscmp(wcsValueName, _T("NameServer")) == 0 347 || _tcscmp(wcsValueName, _T("DhcpNameServer")) == 0) 348 && _tcslen(wcsData) > 0) 349 { 350 extendVectorWithStrings(pHostDnsInfo.servers, std::wstring(wcsData)); 351 } 352 else if (_tcscmp(wcsValueName, _T("SearchList")) == 0 353 && _tcslen(wcsData) > 0) 354 { 355 extendVectorWithStrings(pHostDnsInfo.searchList, std::wstring(wcsData)); 356 } 357 } 358 } 359 } 360 } 361 362 uint8_t fChanged = VBOX_EVENT_NO_CHANGES; 363 /* Compare cached network settings and newly obtained ones. */ 364 if (pHostDnsInfo.servers != m_hostInfoCache.servers) 365 { 366 #ifdef DEBUG 367 LogRel(("Servers changed from:\n")); 368 hostDnsWinDumpList(m_hostInfoCache.servers); 369 LogRel(("to:\n")); 370 hostDnsWinDumpList(pHostDnsInfo.servers); 371 #endif /* DEBUG */ 372 fChanged |= VBOX_EVENT_SERVERS_CHANGED; 373 } 374 375 if (pHostDnsInfo.domain != m_hostInfoCache.domain) 376 { 377 #ifdef DEBUG 378 LogRel(("Domain changed: [%ls]->[%ls].\n", 379 m_hostInfoCache.domain.empty() ? _T("NONE") : (const unsigned short *)m_hostInfoCache.domain.data(), 380 pHostDnsInfo.domain.data())); 381 #endif /* DEBUG */ 382 fChanged |= VBOX_EVENT_DOMAIN_CHANGED; 383 } 384 385 if (pHostDnsInfo.searchList != m_hostInfoCache.searchList) 386 { 387 #ifdef DEBUG 388 LogRel(("SearchList changed from:\n")); 389 hostDnsWinDumpList(m_hostInfoCache.searchList); 390 LogRel(("to:\n")); 391 hostDnsWinDumpList(pHostDnsInfo.searchList); 392 #endif /* DEBUG */ 393 fChanged |= VBOX_EVENT_SEARCHLIST_CHANGED; 394 } 395 396 /* Provide info about changes if requested. */ 397 if (fWhatsChanged) 398 *fWhatsChanged = fChanged; 399 400 /* Update host network configuration cache. */ 401 m_hostInfoCache.servers.clear(); 402 m_hostInfoCache.servers = pHostDnsInfo.servers; 403 m_hostInfoCache.domain.clear(); 404 m_hostInfoCache.domain.assign(pHostDnsInfo.domain); 405 m_hostInfoCache.searchList.clear(); 406 m_hostInfoCache.searchList = pHostDnsInfo.searchList; 407 408 HostDnsMonitor::setInfo(pHostDnsInfo); 409 } 410 411 return S_OK; 412 } 413 414 415 void HostDnsServiceWin::getEventHandles(HANDLE *ahEvents) 416 { 417 AssertReturnVoid(m_aWarehouse.size() > 0); 418 for (int idxHandle = 0; idxHandle < m_aWarehouse.size(); idxHandle++) 419 ahEvents[idxHandle] = m_aWarehouse[idxHandle].hEvent; 91 420 } 92 421 … … 94 423 int HostDnsServiceWin::monitorWorker() 95 424 { 96 registerNotification(m->hKeyTcpipParameters,97 m->haDataEvent[DATA_DNS_UPDATE_EVENT]);98 99 425 monitorThreadInitializationDone(); 100 426 101 DWORD dwRc; 427 uint8_t fWhatsChabged = VBOX_EVENT_NO_CHANGES; 428 429 if (!m_fInitialized) 430 { 431 LogRel(("Host DNS monitor was not initialized properly.\n")); 432 return VERR_INTERNAL_ERROR; 433 } 434 435 HANDLE ahEvents[MAXIMUM_WAIT_OBJECTS]; 436 102 437 while (true) 103 438 { 104 dwRc = WaitForMultipleObjects(DATA_MAX_EVENT, 105 m->haDataEvent, 106 FALSE, 107 INFINITE); 108 AssertMsgReturn(dwRc != WAIT_FAILED, 439 /* Each new iteration we need to update event handles list we monitor. */ 440 RT_ZERO(ahEvents); 441 getEventHandles(ahEvents); 442 443 DWORD rc = WaitForMultipleObjects((DWORD)m_aWarehouse.size(), ahEvents, FALSE, INFINITE); 444 445 AssertMsgReturn(rc != WAIT_FAILED, 109 446 ("WaitForMultipleObjects failed (%d) to wait! Please debug", 110 447 GetLastError()), VERR_INTERNAL_ERROR); 111 448 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 { 449 /* Shutdown requested. */ 450 if (rc == (WAIT_OBJECT_0 + VBOX_OFFSET_SHUTDOWN_EVENT)) break; 451 /* Interfaces amount changed. */ 452 else if (rc == (WAIT_OBJECT_0 + VBOX_OFFSET_TREE_EVENT)) 453 { 454 Log2(("Network interfaces amount changed.\n")); 455 456 /* Drop interface events. */ 457 if (dropSubTreeNotifications()) 458 { 459 /* Drop event which is corresponds to interfaces tree changes. */ 460 if (releaseWarehouseItem(VBOX_OFFSET_TREE_EVENT)) 461 { 462 /* Restart interface tree monitoring. */ 463 if (subscribeTo(const_cast<TCHAR *>(m_pwcKeyRoot), NULL, REG_NOTIFY_CHANGE_NAME)) 464 { 465 /* Restart interface events. */ 466 if (enumerateSubTree()) 467 { 468 Log2(("Monitor restarted successfully.\n")); 469 fWhatsChabged = VBOX_EVENT_NO_CHANGES; 470 updateInfo(&fWhatsChabged); 471 if (fWhatsChabged & VBOX_EVENT_SERVERS_CHANGED) 472 { 473 LogRel(("Notification sent (1).\n")); 474 notifyAll(); 475 } 476 continue; 477 } 478 else 479 LogRel(("Monitor unstable: failed to subscribe network configuration changes.\n")); 480 } 481 else 482 LogRel(("Monitor unstable: failed to subscribe interface changes.\n")); 483 } 484 else 485 LogRel(("Monitor unstable: failed to unsubscribe from interfaces amount changes.\n")); 486 } 487 else 488 LogRel(("Monitor unstable: failed to unsubscribe from previous notifications.\n")); 489 490 /* If something went wrong, we break monitoring. */ 123 491 break; 492 493 } 494 /* DNS update events range. */ 495 else if (rc > (WAIT_OBJECT_0 + VBOX_OFFSET_SUBTREE_EVENTS) && 496 rc < (WAIT_OBJECT_0 + m_aWarehouse.size() - VBOX_OFFSET_SUBTREE_EVENTS)) 497 { 498 Log2(("Network setting has changed at interface %ls.\n", m_aWarehouse[rc - WAIT_OBJECT_0].wcsInterface)); 499 500 /* Drop previous notifications first. */ 501 if (dropSubTreeNotifications()) 502 { 503 /* Re-subscribe. */ 504 if (enumerateSubTree()) 505 { 506 Log2(("Restart monitoring.\n")); 507 fWhatsChabged = VBOX_EVENT_NO_CHANGES; 508 updateInfo(&fWhatsChabged); 509 if (fWhatsChabged & VBOX_EVENT_SERVERS_CHANGED) 510 { 511 LogRel(("Notification sent (2).\n")); 512 notifyAll(); 513 } 514 continue; 515 } 516 else 517 LogRel(("WARNING: Monitor unstable: unable to re-subscribe to notifications.\n")); 518 } 519 else 520 LogRel(("WARNING: Monitor unstable: failed to unsubscribe from previous notifications.\n")); 521 522 /* If something went wrong, we stop monitoring. */ 523 break; 124 524 } 125 525 else 126 { 127 AssertMsgFailedReturn( 128 ("WaitForMultipleObjects returns out of bound index %d. Please debug!", 129 dwRc), 130 VERR_INTERNAL_ERROR); 131 } 132 } 526 AssertMsgFailedReturn(("WaitForMultipleObjects returns out of bound (%d) index %d. Please debug!", m_aWarehouse.size(), rc), VERR_INTERNAL_ERROR); 527 } 528 LogRel(("Monitor thread exited.\n")); 133 529 return VINF_SUCCESS; 134 530 } 135 531 136 137 HRESULT 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_SUCCESS160 || hrc == ERROR_MORE_DATA)161 {162 if ( RTStrICmp("Domain", keyName) == 0163 && cbKeyData > 1164 && cbKeyData < sizeof(abDomain))165 memcpy(abDomain, keyData, cbKeyData);166 167 else if ( RTStrICmp("DhcpDomain", keyName) == 0168 && cbKeyData > 1169 && abDomain[0] == 0170 && cbKeyData < sizeof(abDomain))171 memcpy(abDomain, keyData, cbKeyData);172 173 else if ( RTStrICmp("NameServer", keyName) == 0174 && cbKeyData > 1175 && cbKeyData < sizeof(abNameServers))176 memcpy(abNameServers, keyData, cbKeyData);177 178 else if ( RTStrICmp("DhcpNameServer", keyName) == 0179 && cbKeyData > 1180 && abNameServers[0] == 0181 && cbKeyData < sizeof(abNameServers))182 memcpy(abNameServers, keyData, cbKeyData);183 184 else if ( RTStrICmp("SearchList", keyName) == 0185 && cbKeyData > 1186 && 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 208 void 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 else226 strcpy(address, current);227 228 lst.push_back(std::string(address));229 230 current = next + 1;231 } while(next);232 233 }
Note:
See TracChangeset
for help on using the changeset viewer.