Changeset 52897 in vbox for trunk/src/VBox
- Timestamp:
- Sep 30, 2014 2:45:00 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
r50650 r52897 36 36 37 37 static void dumpHostDnsInformation(const HostDnsInformation&); 38 static void dumpHostDnsStrVector(const std::string&, const std::vector<std:: string>&);38 static void dumpHostDnsStrVector(const std::string&, const std::vector<std::wstring>&); 39 39 40 40 /* Lockee */ … … 66 66 } 67 67 68 inline static void detachVectorOf String(const std::vector<std::string>& v,68 inline static void detachVectorOfWString(const std::vector<std::wstring>& v, 69 69 ComSafeArrayOut(BSTR, aBstrArray)) 70 70 { 71 71 com::SafeArray<BSTR> aBstr(v.size()); 72 72 73 std::vector<std:: string>::const_iterator it;73 std::vector<std::wstring>::const_iterator it; 74 74 75 75 int i = 0; … … 276 276 dumpHostDnsStrVector("Name Server", m->info->servers); 277 277 278 detachVectorOf String(m->info->servers, ComSafeArrayOutArg(aNameServers));278 detachVectorOfWString(m->info->servers, ComSafeArrayOutArg(aNameServers)); 279 279 280 280 return S_OK; … … 307 307 dumpHostDnsStrVector("Search String", m->info->searchList); 308 308 309 detachVectorOf String(m->info->searchList, ComSafeArrayOutArg(aSearchStrings));309 detachVectorOfWString(m->info->searchList, ComSafeArrayOutArg(aSearchStrings)); 310 310 311 311 return S_OK; … … 350 350 351 351 if (!info.domain.empty()) 352 LogRel(("DNS domain: % s\n", info.domain.c_str()));353 } 354 355 356 static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std:: string>& v)352 LogRel(("DNS domain: %ls\n", info.domain.data())); 353 } 354 355 356 static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::wstring>& v) 357 357 { 358 358 int i = 1; 359 for (std::vector<std:: string>::const_iterator it = v.begin();359 for (std::vector<std::wstring>::const_iterator it = v.begin(); 360 360 it != v.end(); 361 361 ++it, ++i) 362 LogRel(("%s %d: % s\n", prefix.c_str(), i, it->c_str()));363 } 362 LogRel(("%s %d: %ls\n", prefix.c_str(), i, it->data())); 363 } -
trunk/src/VBox/Main/src-server/HostDnsService.h
r50263 r52897 57 57 { 58 58 public: 59 std::vector<std:: string> servers;60 std:: string domain;61 std::vector<std:: string> searchList;59 std::vector<std::wstring> servers; 60 std::wstring domain; 61 std::vector<std::wstring> searchList; 62 62 }; 63 63 … … 146 146 # endif 147 147 # ifdef RT_OS_WINDOWS 148 class HostDnsServiceWin : public HostDnsMonitor 148 /* Maximum size of Windows registry key (according to MSDN). */ 149 #define VBOX_KEY_NAME_LEN_MAX (255) 150 class HostDnsServiceWin: public HostDnsMonitor 149 151 { 150 152 public: 151 HostDnsServiceWin(); 152 ~HostDnsServiceWin(); 153 HRESULT init(); 153 154 HostDnsServiceWin(); 155 ~HostDnsServiceWin(); 156 157 HRESULT init(); 154 158 155 159 protected: 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; 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; 166 222 }; 167 223 # endif -
trunk/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp
r50263 r52897 61 61 } 62 62 63 64 63 HRESULT HostDnsServiceResolvConf::readResolvConf() 65 64 { 66 65 struct rcp_state st; 67 66 wchar_t *pwczTmpStr; 67 68 68 st.rcps_flags = RCPSF_NO_STR2IPCONV; 69 69 int rc = rcp_parse(&st, m->resolvConfFilename.c_str()); … … 75 75 { 76 76 AssertBreak(st.rcps_str_nameserver[i]); 77 info.servers.push_back(st.rcps_str_nameserver[i]); 77 78 pwczTmpStr = NULL; 79 rc = RTStrToUtf16(st.rcps_str_nameserver[i], (RTUTF16 **)&pwczTmpStr); 80 if (RT_SUCCESS(rc) && pwczTmpStr) 81 { 82 info.servers.push_back(std::wstring(pwczTmpStr)); 83 RTUtf16Free((RTUTF16 *)pwczTmpStr); 84 } 78 85 } 79 86 80 87 if (st.rcps_domain) 81 info.domain = st.rcps_domain; 88 { 89 pwczTmpStr = NULL; 90 rc = RTStrToUtf16(st.rcps_domain, (RTUTF16 **)&pwczTmpStr); 91 if (RT_SUCCESS(rc) && pwczTmpStr) 92 { 93 info.domain = std::wstring(pwczTmpStr); 94 RTUtf16Free((RTUTF16 *)pwczTmpStr); 95 } 96 } 82 97 83 98 for (unsigned i = 0; i != st.rcps_num_searchlist; ++i) 84 99 { 85 100 AssertBreak(st.rcps_searchlist[i]); 86 info.searchList.push_back(st.rcps_searchlist[i]); 101 pwczTmpStr = NULL; 102 rc = RTStrToUtf16(st.rcps_searchlist[i], (RTUTF16 **)&pwczTmpStr); 103 if (RT_SUCCESS(rc) && pwczTmpStr) 104 { 105 info.searchList.push_back(std::wstring(pwczTmpStr)); 106 RTUtf16Free((RTUTF16 *)pwczTmpStr); 107 } 87 108 } 88 109 setInfo(info); -
trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp
r50263 r52897 18 18 #include <VBox/com/string.h> 19 19 #include <VBox/com/ptr.h> 20 #include <VBox/log.h> 20 21 21 22 … … 162 163 163 164 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; 164 199 } 165 200 … … 195 230 if (domainNameRef) 196 231 { 197 const char *pszDomainName = CFStringGetCStringPtr(domainNameRef, 198 CFStringGetSystemEncoding()); 199 if (pszDomainName) 200 info.domain = pszDomainName; 232 wchar_t *pwszDomainName = darwinCFStringToUtf16(domainNameRef); 233 if (pwszDomainName) 234 { 235 info.domain = std::wstring(pwszDomainName); 236 RTMemFree(pwszDomainName); 237 } 201 238 } 202 239 … … 213 250 continue; 214 251 215 const char *pszServerAddress = CFStringGetCStringPtr(serverAddressRef,216 CFStringGetSystemEncoding());217 if (!pszServerAddress)218 continue; 219 220 info.servers.push_back(std::string(pszServerAddress));252 wchar_t *pwszServerAddress = darwinCFStringToUtf16(serverAddressRef); 253 if (!pwszServerAddress) 254 continue; 255 256 info.servers.push_back(std::wstring(pwszServerAddress)); 257 RTMemFree(pwszServerAddress); 221 258 } 222 259 } … … 234 271 continue; 235 272 236 const char *pszSearchString = CFStringGetCStringPtr(searchStringRef,237 CFStringGetSystemEncoding());238 if (!pszSearchString)239 continue; 240 241 info.searchList.push_back(std::string(pszSearchString));273 wchar_t *pwszSearchString = darwinCFStringToUtf16(searchStringRef); 274 if (!pwszSearchString) 275 continue; 276 277 info.searchList.push_back(std::wstring(pwszSearchString)); 278 RTMemFree(pwszSearchString); 242 279 } 243 280 } -
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.