VirtualBox

Changeset 53122 in vbox for trunk/src


Ignore:
Timestamp:
Oct 22, 2014 8:43:04 PM (10 years ago)
Author:
vboxsync
Message:

Main/HostDnsService: revert r96327 and follow-up r96329 and r96331 to
revert conversion of HostDnsInformation to Unicode.

HostDnsServiceWin.cpp behavioral changes will be redone as a separate
commit against old definition of HostDnsInformation.

Intervening SafeArray cleanup in r96372 is preserved, hopefully
without errors. Please review.

Location:
trunk/src/VBox/Main/src-server
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/HostDnsService.cpp

    r52934 r53122  
    3636
    3737static void dumpHostDnsInformation(const HostDnsInformation&);
    38 static void dumpHostDnsStrVector(const std::string&, const std::vector<std::wstring>&);
     38static void dumpHostDnsStrVector(const std::string&, const std::vector<std::string>&);
    3939
    4040/* Lockee */
     
    6666}
    6767
    68 inline static void detachVectorOfWString(const std::vector<std::wstring>& v,
    69                                          std::vector<com::Utf8Str> &aArray)
     68inline static void detachVectorOfString(const std::vector<std::string>& v,
     69                                        std::vector<com::Utf8Str> &aArray)
    7070{
    7171    aArray.resize(v.size());
    7272    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)
    7474        aArray[i] = Utf8Str(it->c_str());
    7575}
     
    270270    dumpHostDnsStrVector("Name Server", m->info->servers);
    271271
    272     detachVectorOfWString(m->info->servers, aNameServers);
     272    detachVectorOfString(m->info->servers, aNameServers);
    273273
    274274    return S_OK;
     
    301301    dumpHostDnsStrVector("Search String", m->info->searchList);
    302302
    303     detachVectorOfWString(m->info->searchList, aSearchStrings);
     303    detachVectorOfString(m->info->searchList, aSearchStrings);
    304304
    305305    return S_OK;
     
    344344
    345345    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
     350static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
    351351{
    352352    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();
    354354         it != v.end();
    355355         ++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  
    5757{
    5858  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;
    6262};
    6363
     
    146146# endif
    147147# 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
     148class HostDnsServiceWin : public HostDnsMonitor
    151149{
    152150    public:
    153 
    154         HostDnsServiceWin();
    155         ~HostDnsServiceWin();
    156 
    157         HRESULT init();
     151    HostDnsServiceWin();
     152    ~HostDnsServiceWin();
     153    HRESULT init();
    158154
    159155    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;
    222166};
    223167# endif
  • trunk/src/VBox/Main/src-server/HostDnsServiceResolvConf.cpp

    r52932 r53122  
    7878}
    7979
     80
    8081HRESULT HostDnsServiceResolvConf::readResolvConf()
    8182{
    8283    struct rcp_state st;
    83     wchar_t *pwczTmpStr;
    84 
     84   
    8585    st.rcps_flags = RCPSF_NO_STR2IPCONV;
    8686    int rc = rcp_parse(&st, m->resolvConfFilename.c_str());
     
    9292    {
    9393        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]);
    10295    }
    103 
     96   
    10497    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;
    11499
    115100    for (unsigned i = 0; i != st.rcps_num_searchlist; ++i)
    116101    {
    117102        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]);
    125104    }
    126105    setInfo(info);
  • trunk/src/VBox/Main/src-server/darwin/HostDnsServiceDarwin.cpp

    r52901 r53122  
    1818#include <VBox/com/string.h>
    1919#include <VBox/com/ptr.h>
    20 #include <VBox/log.h>
    2120
    2221
     
    163162
    164163    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;
    199164}
    200165
     
    230195    if (domainNameRef)
    231196    {
    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;
    238201    }
    239202
     
    250213                continue;
    251214
    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));
    258221        }
    259222    }
     
    271234                continue;
    272235
    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));
    279242        }
    280243    }
  • 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; -*- */
    182#include <VBox/com/string.h>
    193#include <VBox/com/ptr.h>
    20 #include <VBox/log.h>
     4
    215
    226#include <iprt/assert.h>
     
    2610
    2711#include <string>
    28 #include <sstream>
    2912#include <vector>
    3013#include "../HostDnsService.h"
    3114
    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))
     15struct 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
     25static 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
     39HostDnsServiceWin::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
     62HostDnsServiceWin::~HostDnsServiceWin()
     63{
     64    if (m && !m->hKeyTcpipParameters)
    4965    {
    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;
    6975    }
    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();
    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 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;
    26776}
    26877
     
    27382    AssertComRCReturn(hrc, hrc);
    27483
    275     return updateInfo(NULL);
     84    return updateInfo();
    27685}
    27786
     
    27988void HostDnsServiceWin::monitorThreadShutdown()
    28089{
    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]);
    42091}
    42192
     
    42394int HostDnsServiceWin::monitorWorker()
    42495{
     96    registerNotification(m->hKeyTcpipParameters,
     97                         m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
     98
    42599    monitorThreadInitializationDone();
    426100
    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;
    437102    while (true)
    438103    {
    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,
    446109                        ("WaitForMultipleObjects failed (%d) to wait! Please debug",
    447110                         GetLastError()), VERR_INTERNAL_ERROR);
    448111
    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        {
    491123            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                 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;
    524124        }
    525125        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        }
    527132    }
    528     LogRel(("Monitor thread exited.\n"));
    529133    return VINF_SUCCESS;
    530134}
    531135
     136
     137HRESULT 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
     208void 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