- Timestamp:
- Oct 22, 2014 8:43:04 PM (10 years ago)
- Location:
- trunk/src/VBox/Main/src-server
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/HostDnsService.cpp
r52934 r53122 36 36 37 37 static void dumpHostDnsInformation(const HostDnsInformation&); 38 static void dumpHostDnsStrVector(const std::string&, const std::vector<std:: wstring>&);38 static void dumpHostDnsStrVector(const std::string&, const std::vector<std::string>&); 39 39 40 40 /* Lockee */ … … 66 66 } 67 67 68 inline static void detachVectorOf WString(const std::vector<std::wstring>& v,69 68 inline static void detachVectorOfString(const std::vector<std::string>& v, 69 std::vector<com::Utf8Str> &aArray) 70 70 { 71 71 aArray.resize(v.size()); 72 72 size_t i = 0; 73 for (std::vector<std:: wstring>::const_iterator it = v.begin(); it != v.end(); ++it, ++i)73 for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it, ++i) 74 74 aArray[i] = Utf8Str(it->c_str()); 75 75 } … … 270 270 dumpHostDnsStrVector("Name Server", m->info->servers); 271 271 272 detachVectorOf WString(m->info->servers, aNameServers);272 detachVectorOfString(m->info->servers, aNameServers); 273 273 274 274 return S_OK; … … 301 301 dumpHostDnsStrVector("Search String", m->info->searchList); 302 302 303 detachVectorOf WString(m->info->searchList, aSearchStrings);303 detachVectorOfString(m->info->searchList, aSearchStrings); 304 304 305 305 return S_OK; … … 344 344 345 345 if (!info.domain.empty()) 346 LogRel(("DNS domain: % ls\n", info.domain.data()));347 } 348 349 350 static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std:: wstring>& v)346 LogRel(("DNS domain: %s\n", info.domain.c_str())); 347 } 348 349 350 static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v) 351 351 { 352 352 int i = 1; 353 for (std::vector<std:: wstring>::const_iterator it = v.begin();353 for (std::vector<std::string>::const_iterator it = v.begin(); 354 354 it != v.end(); 355 355 ++it, ++i) 356 LogRel(("%s %d: % ls\n", prefix.c_str(), i, it->data()));357 } 356 LogRel(("%s %d: %s\n", prefix.c_str(), i, it->c_str())); 357 } -
trunk/src/VBox/Main/src-server/HostDnsService.h
r52934 r53122 57 57 { 58 58 public: 59 std::vector<std:: wstring> servers;60 std:: wstring domain;61 std::vector<std:: wstring> searchList;59 std::vector<std::string> servers; 60 std::string domain; 61 std::vector<std::string> searchList; 62 62 }; 63 63 … … 146 146 # endif 147 147 # ifdef RT_OS_WINDOWS 148 /* Maximum size of Windows registry key (according to MSDN). */ 149 #define VBOX_KEY_NAME_LEN_MAX (255) 150 class HostDnsServiceWin: public HostDnsMonitor 148 class HostDnsServiceWin : public HostDnsMonitor 151 149 { 152 150 public: 153 154 HostDnsServiceWin(); 155 ~HostDnsServiceWin(); 156 157 HRESULT init(); 151 HostDnsServiceWin(); 152 ~HostDnsServiceWin(); 153 HRESULT init(); 158 154 159 155 protected: 160 161 virtual void monitorThreadShutdown(); 162 virtual int monitorWorker(); 163 164 private: 165 166 /* This structure is used in order to link Windows registry key with 167 * an event which is generated once the key has been changed (when interface has updated its DNS setting) 168 * or one of the sub-keys has been deleted or added (when interface added or deleted). */ 169 struct Item 170 { 171 HKEY hKey; /** Key handle. */ 172 HANDLE hEvent; /** Event handle. */ 173 TCHAR wcsInterface[VBOX_KEY_NAME_LEN_MAX]; /** Path to key within Windows registry. */ 174 }; 175 176 /* Bit flags to determine what was exactly was changed when Windows triggered event notification. */ 177 enum { 178 VBOX_EVENT_NO_CHANGES = 0, 179 VBOX_EVENT_SERVERS_CHANGED = RT_BIT(1), 180 VBOX_EVENT_DOMAIN_CHANGED = RT_BIT(2), 181 VBOX_EVENT_SEARCHLIST_CHANGED = RT_BIT(3), 182 }; 183 184 /* Keys and events storage. 185 * Size of this vector should not be greater than MAXIMUM_WAIT_OBJECTS because 186 * this is exactly maximum amount of events which we allowed to wait for. */ 187 std::vector<struct Item> m_aWarehouse; 188 /* Cached host network configuration. */ 189 HostDnsInformation m_hostInfoCache; 190 191 /* TCHAR[] constants initialized outside of class definition. */ 192 static const TCHAR m_pwcKeyRoot[]; 193 194 /* m_aWarehouse array offsets. */ 195 enum { 196 VBOX_OFFSET_SHUTDOWN_EVENT = 0, 197 VBOX_OFFSET_TREE_EVENT = 1, 198 VBOX_OFFSET_SUBTREE_EVENTS = 2, 199 }; 200 201 /* Do actual unsubscription for given item. */ 202 bool releaseWarehouseItem(int idxItem); 203 /* Release all allocated resources and unsubscribe from everything. */ 204 void releaseResources(); 205 /* Remove subscription from DNS change notifications and release corresponding resources. */ 206 bool dropSubTreeNotifications(); 207 208 /* Create & add event into the list of events we monitor to. */ 209 bool subscribeTo(TCHAR *wcsPath, TCHAR *wcsInterface, DWORD fFilter); 210 /* Subscribe to DNS changes. */ 211 bool enumerateSubTree(); 212 213 /* Get plain array of event handles. */ 214 void getEventHandles(HANDLE *ahEvents); 215 void extendVectorWithStrings(std::vector<std::wstring>& pVectorToExtend, std::wstring &wcsParameter); 216 HRESULT updateInfo(uint8_t *fWhatsChanged); 217 218 /* This flag indicates whether constructor performed initialization correctly. If not set, 219 * monitorWorker() will not perform any action and will be terminated as soon as there will be 220 * an attempt to run it. */ 221 bool m_fInitialized; 156 virtual void monitorThreadShutdown(); 157 virtual int monitorWorker(); 158 159 private: 160 void strList2List(std::vector<std::string>& lst, char *strLst); 161 HRESULT updateInfo(); 162 163 private: 164 struct Data; 165 Data *m; 222 166 }; 223 167 # endif -
trunk/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp
r52932 r53122 78 78 } 79 79 80 80 81 HRESULT HostDnsServiceResolvConf::readResolvConf() 81 82 { 82 83 struct rcp_state st; 83 wchar_t *pwczTmpStr; 84 84 85 85 st.rcps_flags = RCPSF_NO_STR2IPCONV; 86 86 int rc = rcp_parse(&st, m->resolvConfFilename.c_str()); … … 92 92 { 93 93 AssertBreak(st.rcps_str_nameserver[i]); 94 95 pwczTmpStr = NULL; 96 rc = RTStrToUtf16(st.rcps_str_nameserver[i], (RTUTF16 **)&pwczTmpStr); 97 if (RT_SUCCESS(rc) && pwczTmpStr) 98 { 99 info.servers.push_back(std::wstring(pwczTmpStr)); 100 RTUtf16Free((RTUTF16 *)pwczTmpStr); 101 } 94 info.servers.push_back(st.rcps_str_nameserver[i]); 102 95 } 103 96 104 97 if (st.rcps_domain) 105 { 106 pwczTmpStr = NULL; 107 rc = RTStrToUtf16(st.rcps_domain, (RTUTF16 **)&pwczTmpStr); 108 if (RT_SUCCESS(rc) && pwczTmpStr) 109 { 110 info.domain = std::wstring(pwczTmpStr); 111 RTUtf16Free((RTUTF16 *)pwczTmpStr); 112 } 113 } 98 info.domain = st.rcps_domain; 114 99 115 100 for (unsigned i = 0; i != st.rcps_num_searchlist; ++i) 116 101 { 117 102 AssertBreak(st.rcps_searchlist[i]); 118 pwczTmpStr = NULL; 119 rc = RTStrToUtf16(st.rcps_searchlist[i], (RTUTF16 **)&pwczTmpStr); 120 if (RT_SUCCESS(rc) && pwczTmpStr) 121 { 122 info.searchList.push_back(std::wstring(pwczTmpStr)); 123 RTUtf16Free((RTUTF16 *)pwczTmpStr); 124 } 103 info.searchList.push_back(st.rcps_searchlist[i]); 125 104 } 126 105 setInfo(info); -
trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp
r52901 r53122 18 18 #include <VBox/com/string.h> 19 19 #include <VBox/com/ptr.h> 20 #include <VBox/log.h>21 20 22 21 … … 163 162 164 163 return VINF_SUCCESS; 165 }166 167 168 static wchar_t *darwinCFStringToUtf16(CFStringRef pStringRef)169 {170 /* Number of characters (UTF16 encoded, 2 bytes) in the pStringRef. */171 CFIndex ccStringRef = CFStringGetLength(pStringRef);172 173 if (ccStringRef > 0)174 {175 size_t cbTmpBuf = (size_t)ccStringRef * sizeof(wchar_t) + 1 /* end of string */;176 wchar_t *pTmpBuf = (wchar_t *)RTMemAlloc(cbTmpBuf);177 if (pTmpBuf)178 {179 CFIndex ccConverted = CFStringGetBytes(pStringRef,180 CFRangeMake(0, ccStringRef),181 kCFStringEncodingUTF16,182 0,183 false,184 (UInt8 *)pTmpBuf,185 (CFIndex)cbTmpBuf - 1 /* w/o end of string */,186 NULL);187 if (ccConverted > 0)188 {189 /* Set end of string. */190 pTmpBuf[ccConverted] = 0;191 return pTmpBuf;192 }193 194 RTMemFree(pTmpBuf);195 }196 }197 198 return NULL;199 164 } 200 165 … … 230 195 if (domainNameRef) 231 196 { 232 wchar_t *pwszDomainName = darwinCFStringToUtf16(domainNameRef); 233 if (pwszDomainName) 234 { 235 info.domain = std::wstring(pwszDomainName); 236 RTMemFree(pwszDomainName); 237 } 197 const char *pszDomainName = CFStringGetCStringPtr(domainNameRef, 198 CFStringGetSystemEncoding()); 199 if (pszDomainName) 200 info.domain = pszDomainName; 238 201 } 239 202 … … 250 213 continue; 251 214 252 wchar_t *pwszServerAddress = darwinCFStringToUtf16(serverAddressRef);253 if (!pwszServerAddress)254 continue;255 256 info.servers.push_back(std::wstring(pwszServerAddress)); 257 RTMemFree(pwszServerAddress);215 const char *pszServerAddress = CFStringGetCStringPtr(serverAddressRef, 216 CFStringGetSystemEncoding()); 217 if (!pszServerAddress) 218 continue; 219 220 info.servers.push_back(std::string(pszServerAddress)); 258 221 } 259 222 } … … 271 234 continue; 272 235 273 wchar_t *pwszSearchString = darwinCFStringToUtf16(searchStringRef);274 if (!pwszSearchString)275 continue;276 277 info.searchList.push_back(std::wstring(pwszSearchString)); 278 RTMemFree(pwszSearchString);236 const char *pszSearchString = CFStringGetCStringPtr(searchStringRef, 237 CFStringGetSystemEncoding()); 238 if (!pszSearchString) 239 continue; 240 241 info.searchList.push_back(std::string(pszSearchString)); 279 242 } 280 243 } -
trunk/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp
r52900 r53122 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 1 /* -*- indent-tabs-mode: nil; -*- */ 18 2 #include <VBox/com/string.h> 19 3 #include <VBox/com/ptr.h> 20 #include <VBox/log.h> 4 21 5 22 6 #include <iprt/assert.h> … … 26 10 27 11 #include <string> 28 #include <sstream>29 12 #include <vector> 30 13 #include "../HostDnsService.h" 31 14 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)) 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())); 59 } 60 61 62 HostDnsServiceWin::~HostDnsServiceWin() 63 { 64 if (m && !m->hKeyTcpipParameters) 49 65 { 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")); 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; 69 75 } 70 else71 /* 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();75 }76 77 78 HostDnsServiceWin::~HostDnsServiceWin()79 {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 here90 * (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 case164 * 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 else182 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 to203 * 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 and233 * 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 else252 LogRel(("Unable to open interfaces list (1).\n"));253 }254 RegCloseKey(hTmpKey);255 return true;256 }257 else258 LogRel(("Unable to open interfaces list (2).\n"));259 }260 else261 LogRel(("Unable to open interfaces list (3).\n"));262 RegCloseKey(hTmpKey);263 }264 else265 LogRel(("Unable to open interfaces list (4).\n"));266 return false;267 76 } 268 77 … … 273 82 AssertComRCReturn(hrc, hrc); 274 83 275 return updateInfo( NULL);84 return updateInfo(); 276 85 } 277 86 … … 279 88 void HostDnsServiceWin::monitorThreadShutdown() 280 89 { 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; 90 SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]); 420 91 } 421 92 … … 423 94 int HostDnsServiceWin::monitorWorker() 424 95 { 96 registerNotification(m->hKeyTcpipParameters, 97 m->haDataEvent[DATA_DNS_UPDATE_EVENT]); 98 425 99 monitorThreadInitializationDone(); 426 100 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 101 DWORD dwRc; 437 102 while (true) 438 103 { 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, 104 dwRc = WaitForMultipleObjects(DATA_MAX_EVENT, 105 m->haDataEvent, 106 FALSE, 107 INFINITE); 108 AssertMsgReturn(dwRc != WAIT_FAILED, 446 109 ("WaitForMultipleObjects failed (%d) to wait! Please debug", 447 110 GetLastError()), VERR_INTERNAL_ERROR); 448 111 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. */ 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 { 491 123 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()))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 else517 LogRel(("WARNING: Monitor unstable: unable to re-subscribe to notifications.\n"));518 }519 else520 LogRel(("WARNING: Monitor unstable: failed to unsubscribe from previous notifications.\n"));521 522 /* If something went wrong, we stop monitoring. */523 break;524 124 } 525 125 else 526 AssertMsgFailedReturn(("WaitForMultipleObjects returns out of bound (%d) index %d. Please debug!\n", m_aWarehouse.size(), rc), VERR_INTERNAL_ERROR); 126 { 127 AssertMsgFailedReturn( 128 ("WaitForMultipleObjects returns out of bound index %d. Please debug!", 129 dwRc), 130 VERR_INTERNAL_ERROR); 131 } 527 132 } 528 LogRel(("Monitor thread exited.\n"));529 133 return VINF_SUCCESS; 530 134 } 531 135 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_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 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 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 TracChangeset
for help on using the changeset viewer.