VirtualBox

Ignore:
Timestamp:
Oct 29, 2014 4:26:20 PM (10 years ago)
Author:
vboxsync
Message:

Main/HostDnsService: brush up old Windows code. In general no
functional change is intended, but make search list handling follow
Windows behavior.

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
    219#include <VBox/com/string.h>
    320#include <VBox/com/ptr.h>
    421
    5 
    622#include <iprt/assert.h>
    723#include <iprt/err.h>
     24#include <VBox/log.h>
    825
    926#include <Windows.h>
    1027
     28#include <algorithm>
     29#include <sstream>
    1130#include <string>
    1231#include <vector>
    13 #include "../HostDnsService.h"
    1432
    1533struct HostDnsServiceWin::Data
    1634{
    17     HostDnsServiceWin::Data(){}
    1835    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
    2139#define DATA_MAX_EVENT        2
    2240    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    }
    2359};
     60
     61
     62HostDnsServiceWin::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
     94HostDnsServiceWin::~HostDnsServiceWin()
     95{
     96    if (m != NULL)
     97        delete m;
     98}
     99
     100
     101HRESULT 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
     114void HostDnsServiceWin::monitorThreadShutdown()
     115{
     116    Assert(m != NULL);
     117    SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
     118}
     119
    24120
    25121static inline int registerNotification(const HKEY& hKey, HANDLE& hEvent)
     
    37133}
    38134
    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 
    93135
    94136int HostDnsServiceWin::monitorWorker()
    95137{
     138    Assert(m != NULL);
     139
    96140    registerNotification(m->hKeyTcpipParameters,
    97141                         m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
     
    99143    monitorThreadInitializationDone();
    100144
    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)
    113156        {
    114157            updateInfo();
    115158            notifyAll();
     159
    116160            ResetEvent(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
    117161            registerNotification(m->hKeyTcpipParameters,
     
    119163
    120164        }
    121         else if ((dwRc - WAIT_OBJECT_0) == DATA_SHUTDOWN_EVENT)
    122         {
    123             break;
    124         }
    125165        else
    126166        {
    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
    133175    return VINF_SUCCESS;
    134176}
    135177
    136178
     179void 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
    137200HRESULT HostDnsServiceWin::updateInfo()
    138201{
    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];
    152212        DWORD cbKeyName = sizeof(keyName);
    153213        DWORD keyType = 0;
    154         BYTE keyData[1024];
     214        char keyData[1024];
    155215        DWORD cbKeyData = sizeof(keyData);
    156216
    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
    194266    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();
    201290
    202291    HostDnsMonitor::setInfo(info);
     
    204293    return S_OK;
    205294}
    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.

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