HostDnsServiceWin.cpp revision 510229a86fcdcdf2eb0b9540e2981460eab322d5
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync/* -*- indent-tabs-mode: nil; -*- */
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync#include <VBox/com/string.h>
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync#include <VBox/com/ptr.h>
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync#include <iprt/assert.h>
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync#include <iprt/err.h>
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync#include <Windows.h>
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
7a0e5c38eeca5147034ace6fe624de57ac2988ddvboxsync#include <string>
7a0e5c38eeca5147034ace6fe624de57ac2988ddvboxsync#include <vector>
7a0e5c38eeca5147034ace6fe624de57ac2988ddvboxsync#include "../HostDnsService.h"
7a0e5c38eeca5147034ace6fe624de57ac2988ddvboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsyncstruct HostDnsServiceWin::Data
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync{
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync HostDnsServiceWin::Data(){}
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync HKEY hKeyTcpipParameters;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync#define DATA_DNS_UPDATE_EVENT 0
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync#define DATA_SHUTDOWN_EVENT 1
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync#define DATA_MAX_EVENT 2
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync HANDLE haDataEvent[DATA_MAX_EVENT];
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync};
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsyncstatic inline int registerNotification(const HKEY& hKey, HANDLE& hEvent)
735076496e14763dcdef4b43202e7665d4a8da43vboxsync{
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync LONG lrc = RegNotifyChangeKeyValue(hKey,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync TRUE,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync REG_NOTIFY_CHANGE_LAST_SET,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync hEvent,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync TRUE);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync AssertMsgReturn(lrc == ERROR_SUCCESS,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync ("Failed to register event on the key. Please debug me!"),
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync VERR_INTERNAL_ERROR);
735076496e14763dcdef4b43202e7665d4a8da43vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync return VINF_SUCCESS;
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync}
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsyncHostDnsServiceWin::HostDnsServiceWin():HostDnsMonitor(true), m(NULL)
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync{
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync m = new Data();
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync m->haDataEvent[DATA_DNS_UPDATE_EVENT] = CreateEvent(NULL,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync TRUE, FALSE, NULL);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync AssertReleaseMsg(m->haDataEvent[DATA_DNS_UPDATE_EVENT],
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync ("Failed to create event for DNS event (%d)\n", GetLastError()));
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync m->haDataEvent[DATA_SHUTDOWN_EVENT] = CreateEvent(NULL,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync TRUE, FALSE, NULL);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync AssertReleaseMsg(m->haDataEvent[DATA_SHUTDOWN_EVENT],
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync ("Failed to create event for Shutdown signal (%d)\n", GetLastError()));
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync LONG lrc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync 0, KEY_READ|KEY_NOTIFY, &m->hKeyTcpipParameters);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync AssertReleaseMsg(lrc == ERROR_SUCCESS,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync ("Failed to open Registry Key for read and update notifications (%d)\n",
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync GetLastError()));
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync}
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsyncHostDnsServiceWin::~HostDnsServiceWin()
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync{
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync if (m && !m->hKeyTcpipParameters)
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync {
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync RegCloseKey(m->hKeyTcpipParameters);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync m->hKeyTcpipParameters = 0;
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync CloseHandle(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync CloseHandle(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync delete m;
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync m = NULL;
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync }
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync}
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
3f2299591cfeb8a37a3578bef9c44c1790860948vboxsyncHRESULT HostDnsServiceWin::init()
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync{
0faefdb9edd752514d5dfed8353118e47e57f0ebvboxsync HRESULT hrc = HostDnsMonitor::init();
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync AssertComRCReturn(hrc, hrc);
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync return updateInfo();
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync}
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsyncvoid HostDnsServiceWin::monitorThreadShutdown()
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync{
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync SetEvent(m->haDataEvent[DATA_SHUTDOWN_EVENT]);
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync}
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsyncint HostDnsServiceWin::monitorWorker()
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync{
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync registerNotification(m->hKeyTcpipParameters,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync monitorThreadInitializationDone();
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync DWORD dwRc;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync while (true)
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync {
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync dwRc = WaitForMultipleObjects(DATA_MAX_EVENT,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync m->haDataEvent,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync FALSE,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync INFINITE);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync AssertMsgReturn(dwRc != WAIT_FAILED,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync ("WaitForMultipleObjects failed (%d) to wait! Please debug",
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync GetLastError()), VERR_INTERNAL_ERROR);
735076496e14763dcdef4b43202e7665d4a8da43vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync if ((dwRc - WAIT_OBJECT_0) == DATA_DNS_UPDATE_EVENT)
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync {
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync updateInfo();
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync notifyAll();
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync ResetEvent(m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync registerNotification(m->hKeyTcpipParameters,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync m->haDataEvent[DATA_DNS_UPDATE_EVENT]);
735076496e14763dcdef4b43202e7665d4a8da43vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync }
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync else if ((dwRc - WAIT_OBJECT_0) == DATA_SHUTDOWN_EVENT)
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync {
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync break;
dbbd0cae65188dffbd927bdde2d88cbeec2e26davboxsync }
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync else
735076496e14763dcdef4b43202e7665d4a8da43vboxsync {
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync AssertMsgFailedReturn(
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync ("WaitForMultipleObjects returns out of bound index %d. Please debug!",
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync dwRc),
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync VERR_INTERNAL_ERROR);
735076496e14763dcdef4b43202e7665d4a8da43vboxsync }
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync }
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync return VINF_SUCCESS;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync}
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510b14148124a664875cdb3a996433bd92c9324evboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsyncHRESULT HostDnsServiceWin::updateInfo()
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync{
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync HRESULT hrc;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync DWORD regIndex;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync BYTE abDomain[256];
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync BYTE abNameServers[256];
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync BYTE abSearchList[256];
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync RT_ZERO(abDomain);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync RT_ZERO(abNameServers);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync RT_ZERO(abSearchList);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync regIndex = 0;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync do {
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync CHAR keyName[256];
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync DWORD cbKeyName = sizeof(keyName);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync DWORD keyType = 0;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync BYTE keyData[1024];
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync DWORD cbKeyData = sizeof(keyData);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync hrc = RegEnumValueA(m->hKeyTcpipParameters, regIndex, keyName, &cbKeyName, 0,
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync &keyType, keyData, &cbKeyData);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync if ( hrc == ERROR_SUCCESS
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync || hrc == ERROR_MORE_DATA)
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync {
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync if ( RTStrICmp("Domain", keyName) == 0
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData > 1
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData < sizeof(abDomain))
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync memcpy(abDomain, keyData, cbKeyData);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync else if ( RTStrICmp("DhcpDomain", keyName) == 0
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData > 1
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && abDomain[0] == 0
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData < sizeof(abDomain))
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync memcpy(abDomain, keyData, cbKeyData);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync else if ( RTStrICmp("NameServer", keyName) == 0
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData > 1
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData < sizeof(abNameServers))
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync memcpy(abNameServers, keyData, cbKeyData);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync else if ( RTStrICmp("DhcpNameServer", keyName) == 0
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData > 1
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && abNameServers[0] == 0
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData < sizeof(abNameServers))
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync memcpy(abNameServers, keyData, cbKeyData);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync else if ( RTStrICmp("SearchList", keyName) == 0
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData > 1
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync && cbKeyData < sizeof(abSearchList))
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync memcpy(abSearchList, keyData, cbKeyData);
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync }
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync regIndex++;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync } while (hrc != ERROR_NO_MORE_ITEMS);
bca22f037c4fa4df62f7244c27686c0a491821b8vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync /* OK, now parse and update DNS structures. */
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync /* domain name */
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync HostDnsInformation info;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync info.domain = (char*)abDomain;
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync /* server list */
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync strList2List(info.servers, (char *)abNameServers);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync /* search list */
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync strList2List(info.searchList, (char *)abSearchList);
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync HostDnsMonitor::setInfo(info);
3f2299591cfeb8a37a3578bef9c44c1790860948vboxsync
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync return S_OK;
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync}
3f2299591cfeb8a37a3578bef9c44c1790860948vboxsync
8dfc5e89cd3421bb0602f33768f00c1f1d40b1d2vboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsyncvoid HostDnsServiceWin::strList2List(std::vector<std::string>& lst, char *strLst)
735076496e14763dcdef4b43202e7665d4a8da43vboxsync{
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync char *next, *current;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync char address[512];
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync AssertPtrReturnVoid(strLst);
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync if (strlen(strLst) == 0)
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync return;
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync current = strLst;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync do {
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync RT_ZERO(address);
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync next = RTStrStr(current, " ");
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync if (next)
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync strncpy(address, current, RT_MIN(sizeof(address)-1, next - current));
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync else
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync strcpy(address, current);
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync lst.push_back(std::string(address));
63fdb92b88f31446f6ea53241c0d127677c71c7evboxsync
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync current = next + 1;
510229a86fcdcdf2eb0b9540e2981460eab322d5vboxsync } while(next);
735076496e14763dcdef4b43202e7665d4a8da43vboxsync
18b1f1bb3429f8bfc1a52cfaeb2445e9fb1f55cdvboxsync}