Changeset 53165 in vbox for trunk/src/VBox/Main/src-server/win
- Timestamp:
- Oct 29, 2014 4:26:20 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/win/HostDnsServiceWin.cpp
r53159 r53165 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 #include "../HostDnsService.h" 18 2 19 #include <VBox/com/string.h> 3 20 #include <VBox/com/ptr.h> 4 21 5 6 22 #include <iprt/assert.h> 7 23 #include <iprt/err.h> 24 #include <VBox/log.h> 8 25 9 26 #include <Windows.h> 10 27 28 #include <algorithm> 29 #include <sstream> 11 30 #include <string> 12 31 #include <vector> 13 #include "../HostDnsService.h"14 32 15 33 struct HostDnsServiceWin::Data 16 34 { 17 HostDnsServiceWin::Data(){}18 35 HKEY hKeyTcpipParameters; 19 #define DATA_DNS_UPDATE_EVENT 0 20 #define DATA_SHUTDOWN_EVENT 1 36 37 #define DATA_SHUTDOWN_EVENT 0 38 #define DATA_DNS_UPDATE_EVENT 1 21 39 #define DATA_MAX_EVENT 2 22 40 HANDLE haDataEvent[DATA_MAX_EVENT]; 41 42 Data() 43 { 44 hKeyTcpipParameters = NULL; 45 46 for (size_t i = 0; i < DATA_MAX_EVENT; ++i) 47 haDataEvent[i] = NULL; 48 } 49 50 ~Data() 51 { 52 if (hKeyTcpipParameters != NULL) 53 RegCloseKey(hKeyTcpipParameters); 54 55 for (size_t i = 0; i < DATA_MAX_EVENT; ++i) 56 if (haDataEvent[i] != NULL) 57 CloseHandle(haDataEvent[i]); 58 } 23 59 }; 60 61 62 HostDnsServiceWin::HostDnsServiceWin() 63 : HostDnsMonitor(true), 64 m(NULL) 65 { 66 std::auto_ptr<Data> data(new Data()); 67 LONG lrc; 68 69 lrc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, 70 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 71 0, 72 KEY_READ|KEY_NOTIFY, 73 &data->hKeyTcpipParameters); 74 if (lrc != ERROR_SUCCESS) 75 { 76 LogRel(("HostDnsServiceWin: failed to open key Tcpip\\Parameters (error %d)\n", lrc)); 77 return; 78 } 79 80 for (size_t i = 0; i < DATA_MAX_EVENT; ++i) 81 { 82 data->haDataEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL); 83 if (data->haDataEvent[i] == NULL) 84 { 85 LogRel(("HostDnsServiceWin: failed to create event (error %d)\n", GetLastError())); 86 return; 87 } 88 } 89 90 m = data.release(); 91 } 92 93 94 HostDnsServiceWin::~HostDnsServiceWin() 95 { 96 if (m != NULL) 97 delete m; 98 } 99 100 101 HRESULT HostDnsServiceWin::init() 102 { 103 if (m == NULL) 104 return E_FAIL; 105 106 HRESULT hrc = HostDnsMonitor::init(); 107 if (FAILED(hrc)) 108 return hrc; 109 110 return updateInfo(); 111 } 112 113 114 void HostDnsServiceWin::monitorThreadShutdown() 115 { 116 Assert(m != NULL); 117 SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]); 118 } 119 24 120 25 121 static inline int registerNotification(const HKEY& hKey, HANDLE& hEvent) … … 37 133 } 38 134 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)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 79 HRESULT HostDnsServiceWin::init()80 {81 HRESULT hrc = HostDnsMonitor::init();82 AssertComRCReturn(hrc, hrc);83 84 return updateInfo();85 }86 87 88 void HostDnsServiceWin::monitorThreadShutdown()89 {90 SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]);91 }92 93 135 94 136 int HostDnsServiceWin::monitorWorker() 95 137 { 138 Assert(m != NULL); 139 96 140 registerNotification(m->hKeyTcpipParameters, 97 141 m->haDataEvent[DATA_DNS_UPDATE_EVENT]); … … 99 143 monitorThreadInitializationDone(); 100 144 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) 145 for (;;) 146 { 147 DWORD dwReady; 148 149 dwReady = WaitForMultipleObjects(DATA_MAX_EVENT, m->haDataEvent, 150 FALSE, INFINITE); 151 152 if (dwReady == WAIT_OBJECT_0 + DATA_SHUTDOWN_EVENT) 153 break; 154 155 if (dwReady == WAIT_OBJECT_0 + DATA_DNS_UPDATE_EVENT) 113 156 { 114 157 updateInfo(); 115 158 notifyAll(); 159 116 160 ResetEvent(m->haDataEvent[DATA_DNS_UPDATE_EVENT]); 117 161 registerNotification(m->hKeyTcpipParameters, … … 119 163 120 164 } 121 else if ((dwRc - WAIT_OBJECT_0) == DATA_SHUTDOWN_EVENT)122 {123 break;124 }125 165 else 126 166 { 127 AssertMsgFailedReturn( 128 ("WaitForMultipleObjects returns out of bound index %d. Please debug!", 129 dwRc), 130 VERR_INTERNAL_ERROR); 131 } 132 } 167 if (dwReady == WAIT_FAILED) 168 LogRel(("HostDnsServiceWin: WaitForMultipleObjects failed: error %d\n", GetLastError())); 169 else 170 LogRel(("HostDnsServiceWin: WaitForMultipleObjects unexpected return value %d\n", dwReady)); 171 return VERR_INTERNAL_ERROR; 172 } 173 } 174 133 175 return VINF_SUCCESS; 134 176 } 135 177 136 178 179 void vappend(std::vector<std::string> &v, const std::string &s, char sep = ' ') 180 { 181 if (s.empty()) 182 return; 183 184 std::istringstream stream(s); 185 std::string substr; 186 187 while (std::getline(stream, substr, sep)) 188 { 189 if (substr.empty()) 190 continue; 191 192 if (std::find(v.cbegin(), v.cend(), substr) != v.cend()) 193 continue; 194 195 v.push_back(substr); 196 } 197 } 198 199 137 200 HRESULT HostDnsServiceWin::updateInfo() 138 201 { 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]; 202 LONG lrc; 203 204 std::string strNameServer; 205 std::string strDomain; 206 std::string strDhcpNameServer; 207 std::string strDhcpDomain; 208 std::string strSearchList; /* NB: comma separated, no spaces */ 209 210 for (DWORD regIndex = 0; /**/; ++regIndex) { 211 char keyName[256]; 152 212 DWORD cbKeyName = sizeof(keyName); 153 213 DWORD keyType = 0; 154 BYTEkeyData[1024];214 char keyData[1024]; 155 215 DWORD cbKeyData = sizeof(keyData); 156 216 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 */ 217 lrc = RegEnumValueA(m->hKeyTcpipParameters, regIndex, 218 keyName, &cbKeyName, 0, 219 &keyType, (LPBYTE)keyData, &cbKeyData); 220 221 if (lrc == ERROR_NO_MORE_ITEMS) 222 break; 223 224 if (lrc == ERROR_MORE_DATA) /* buffer too small; handle? */ 225 continue; 226 227 if (lrc != ERROR_SUCCESS) 228 { 229 LogRel(("HostDnsServiceWin: RegEnumValue error %d\n", (int)lrc)); 230 return E_FAIL; 231 } 232 233 if (keyType != REG_SZ) 234 continue; 235 236 if (cbKeyData > 0 && keyData[cbKeyData - 1] == '\0') 237 --cbKeyData; /* don't count trailing NUL if present */ 238 239 if (RTStrICmp("NameServer", keyName) == 0) 240 { 241 strNameServer.assign(keyData, cbKeyData); 242 Log2(("... NameServer=\"%s\"\n", strNameServer.c_str())); 243 } 244 else if (RTStrICmp("Domain", keyName) == 0) 245 { 246 strDomain.assign(keyData, cbKeyData); 247 Log2(("... Domain=\"%s\"\n", strDomain.c_str())); 248 } 249 else if (RTStrICmp("DhcpNameServer", keyName) == 0) 250 { 251 strDhcpNameServer.assign(keyData, cbKeyData); 252 Log2(("... DhcpNameServer=\"%s\"\n", strDhcpNameServer.c_str())); 253 } 254 else if (RTStrICmp("DhcpDomain", keyName) == 0) 255 { 256 strDhcpDomain.assign(keyData, cbKeyData); 257 Log2(("... DhcpDomain=\"%s\"\n", strDhcpDomain.c_str())); 258 } 259 else if (RTStrICmp("SearchList", keyName) == 0) 260 { 261 strSearchList.assign(keyData, cbKeyData); 262 Log2(("... SearchList=\"%s\"\n", strSearchList.c_str())); 263 } 264 } 265 194 266 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); 267 268 if (!strNameServer.empty()) 269 vappend(info.servers, strNameServer); 270 else if (!strDhcpNameServer.empty()) 271 vappend(info.servers, strDhcpNameServer); 272 273 if (!strDomain.empty()) 274 { 275 info.domain = strDomain; 276 277 info.searchList.push_back(strDomain); 278 if (!strDhcpDomain.empty() && strDhcpDomain != strDomain) 279 info.searchList.push_back(strDhcpDomain); 280 } 281 else if (!strDhcpDomain.empty()) 282 { 283 info.domain = strDhcpDomain; 284 info.searchList.push_back(strDomain); 285 } 286 287 vappend(info.searchList, strSearchList, ','); 288 if (info.searchList.size() == 1) 289 info.searchList.clear(); 201 290 202 291 HostDnsMonitor::setInfo(info); … … 204 293 return S_OK; 205 294 } 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.