diff options
author | Adam Ierymenko <adam.ierymenko@zerotier.com> | 2014-03-06 14:06:31 -0800 |
---|---|---|
committer | Adam Ierymenko <adam.ierymenko@zerotier.com> | 2014-03-06 14:06:31 -0800 |
commit | 742261c7fc8181e5c1a7567d9fdf51518d90c8bf (patch) | |
tree | 7a64ecc93c3d32a6bdd4d2ece870eb03eb052ec3 /node | |
parent | 939cdc82a2041701c9f08c1745d0175f2c4f62c8 (diff) | |
download | infinitytier-742261c7fc8181e5c1a7567d9fdf51518d90c8bf.tar.gz infinitytier-742261c7fc8181e5c1a7567d9fdf51518d90c8bf.zip |
(1) Fix menu bar item font size on Windows, (2) fix for possible Windows EthernetTap infinite loop while enumerating registry.
Diffstat (limited to 'node')
-rw-r--r-- | node/EthernetTap.cpp | 303 |
1 files changed, 173 insertions, 130 deletions
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp index 8828b873..61e9fbca 100644 --- a/node/EthernetTap.cpp +++ b/node/EthernetTap.cpp @@ -1108,117 +1108,129 @@ EthernetTap::EthernetTap( std::set<std::string> existingDeviceInstances; std::string mySubkeyName; - // Enumerate tap instances and look for one tagged with this tag - for(DWORD subkeyIndex=0;subkeyIndex!=-1;) { + // Look for the tap instance that corresponds with our interface tag (network ID) + for(DWORD subkeyIndex=0;;++subkeyIndex) { DWORD type; DWORD dataLen; DWORD subkeyNameLen = sizeof(subkeyName); DWORD subkeyClassLen = sizeof(subkeyClass); FILETIME lastWriteTime; - switch (RegEnumKeyExA(nwAdapters,subkeyIndex++,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime)) { - case ERROR_NO_MORE_ITEMS: subkeyIndex = -1; break; - case ERROR_SUCCESS: - type = 0; - dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { - data[dataLen] = '\0'; - if (!strnicmp(data,"zttap",5)) { - std::string instanceId; - type = 0; - dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { - instanceId.assign(data,dataLen); - existingDeviceInstances.insert(instanceId); - } + if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) { + type = 0; + dataLen = sizeof(data); + if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { + data[dataLen] = '\0'; + if (!strnicmp(data,"zttap",5)) { + std::string instanceId; + type = 0; + dataLen = sizeof(data); + if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { + instanceId.assign(data,dataLen); + existingDeviceInstances.insert(instanceId); + } - std::string instanceIdPath; + std::string instanceIdPath; + type = 0; + dataLen = sizeof(data); + if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) + instanceIdPath.assign(data,dataLen); + + if ((_myDeviceInstanceId.length() == 0)&&(instanceId.length() != 0)&&(instanceIdPath.length() != 0)) { type = 0; dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) - instanceIdPath.assign(data,dataLen); - - if ((_myDeviceInstanceId.length() == 0)&&(instanceId.length() != 0)&&(instanceIdPath.length() != 0)) { - type = 0; - dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { - data[dataLen] = '\0'; - if (!strcmp(data,tag)) { - _myDeviceInstanceId = instanceId; - _myDeviceInstanceIdPath = instanceIdPath; - mySubkeyName = subkeyName; - subkeyIndex = -1; // break outer loop - } + if (RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { + data[dataLen] = '\0'; + if (!strcmp(data,tag)) { + _myDeviceInstanceId = instanceId; + _myDeviceInstanceIdPath = instanceIdPath; + mySubkeyName = subkeyName; + break; // found it! } } } } - break; - } + } + } else break; // no more subkeys or error occurred enumerating them } // If there is no device, try to create one if (_myDeviceInstanceId.length() == 0) { + // Log devcon output to a file + HANDLE devconLog = CreateFileA((_r->homePath + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + if (devconLog == INVALID_HANDLE_VALUE) { + LOG("WARNING: unable to open devcon.log"); + } else { + SetFilePointer(devconLog,0,0,FILE_END); + } + // Execute devcon to install an instance of the Microsoft Loopback Adapter STARTUPINFOA startupInfo; startupInfo.cb = sizeof(startupInfo); + if (devconLog != INVALID_HANDLE_VALUE) { + SetFilePointer(devconLog,0,0,FILE_END); + startupInfo.hStdOutput = devconLog; + startupInfo.hStdError = devconLog; + } PROCESS_INFORMATION processInfo; memset(&startupInfo,0,sizeof(STARTUPINFOA)); memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" install \"" + _r->homePath + tapDriver + "\" zttap200").c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) { RegCloseKey(nwAdapters); + if (devconLog != INVALID_HANDLE_VALUE) + CloseHandle(devconLog); throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon); } WaitForSingleObject(processInfo.hProcess,INFINITE); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); - + + if (devconLog != INVALID_HANDLE_VALUE) + CloseHandle(devconLog); + // Scan for the new instance by simply looking for taps that weren't - // there originally. - for(DWORD subkeyIndex=0;subkeyIndex!=-1;) { + // there originally. The static mutex we lock ensures this can't step + // on its own toes. + for(DWORD subkeyIndex=0;;++subkeyIndex) { DWORD type; DWORD dataLen; DWORD subkeyNameLen = sizeof(subkeyName); DWORD subkeyClassLen = sizeof(subkeyClass); FILETIME lastWriteTime; - switch (RegEnumKeyExA(nwAdapters,subkeyIndex++,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime)) { - case ERROR_NO_MORE_ITEMS: subkeyIndex = -1; break; - case ERROR_SUCCESS: - type = 0; - dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { - data[dataLen] = '\0'; - if (!strnicmp(data,"zttap",5)) { - type = 0; - dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { - if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) { - RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,(DWORD)(strlen(tag)+1)); - _myDeviceInstanceId.assign(data,dataLen); - type = 0; - dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) - _myDeviceInstanceIdPath.assign(data,dataLen); - mySubkeyName = subkeyName; - - // Disable DHCP by default on newly created devices - HKEY tcpIpInterfaces; - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) { - DWORD enable = 0; - RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable)); - RegCloseKey(tcpIpInterfaces); - } - - subkeyIndex = -1; // break outer loop + if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) { + type = 0; + dataLen = sizeof(data); + if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { + data[dataLen] = '\0'; + if (!strnicmp(data,"zttap",5)) { + type = 0; + dataLen = sizeof(data); + if (RegGetValueA(nwAdapters,subkeyName,"NetCfgInstanceId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { + if (existingDeviceInstances.count(std::string(data,dataLen)) == 0) { + RegSetKeyValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",REG_SZ,tag,(DWORD)(strlen(tag)+1)); + _myDeviceInstanceId.assign(data,dataLen); + type = 0; + dataLen = sizeof(data); + if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) + _myDeviceInstanceIdPath.assign(data,dataLen); + mySubkeyName = subkeyName; + + // Disable DHCP by default on newly created devices + HKEY tcpIpInterfaces; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces",0,KEY_READ|KEY_WRITE,&tcpIpInterfaces) == ERROR_SUCCESS) { + DWORD enable = 0; + RegSetKeyValueA(tcpIpInterfaces,_myDeviceInstanceId.c_str(),"EnableDHCP",REG_DWORD,&enable,sizeof(enable)); + RegCloseKey(tcpIpInterfaces); } + + break; // found it! } } } - break; - } + } + } else break; // no more keys or error occurred } } - // If we have a device, configure it if (_myDeviceInstanceId.length() > 0) { char tmps[4096]; unsigned int tmpsl = Utils::snprintf(tmps,sizeof(tmps),"%.2X-%.2X-%.2X-%.2X-%.2X-%.2X",(unsigned int)mac.data[0],(unsigned int)mac.data[1],(unsigned int)mac.data[2],(unsigned int)mac.data[3],(unsigned int)mac.data[4],(unsigned int)mac.data[5]) + 1; @@ -1228,16 +1240,14 @@ EthernetTap::EthernetTap( RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"MTU",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp)); tmp = 0; RegSetKeyValueA(nwAdapters,mySubkeyName.c_str(),"EnableDHCP",REG_DWORD,(LPCVOID)&tmp,sizeof(tmp)); + } else { + RegCloseKey(nwAdapters); + throw std::runtime_error("unable to find or create tap adapter"); } - // Done with registry RegCloseKey(nwAdapters); - // If we didn't get a device, we can't start - if (_myDeviceInstanceId.length() == 0) - throw std::runtime_error("unable to create new tap adapter"); - - // Convert device GUID junk... blech + // Convert device GUID junk... blech... is there an easier way to do this? { char nobraces[128]; const char *nbtmp1 = _myDeviceInstanceId.c_str(); @@ -1254,32 +1264,51 @@ EthernetTap::EthernetTap( // Disable and enable interface to ensure registry settings take effect { - STARTUPINFOA startupInfo; - startupInfo.cb = sizeof(startupInfo); - PROCESS_INFORMATION processInfo; - memset(&startupInfo,0,sizeof(STARTUPINFOA)); - memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); - if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" disable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) { - RegCloseKey(nwAdapters); - throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon); + HANDLE devconLog = CreateFileA((_r->homePath + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + if (devconLog != INVALID_HANDLE_VALUE) + SetFilePointer(devconLog,0,0,FILE_END); + { + STARTUPINFOA startupInfo; + startupInfo.cb = sizeof(startupInfo); + if (devconLog != INVALID_HANDLE_VALUE) { + startupInfo.hStdOutput = devconLog; + startupInfo.hStdError = devconLog; + } + PROCESS_INFORMATION processInfo; + memset(&startupInfo,0,sizeof(STARTUPINFOA)); + memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); + if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" disable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) { + RegCloseKey(nwAdapters); + if (devconLog != INVALID_HANDLE_VALUE) + CloseHandle(devconLog); + throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon); + } + WaitForSingleObject(processInfo.hProcess,INFINITE); + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); } - WaitForSingleObject(processInfo.hProcess,INFINITE); - CloseHandle(processInfo.hProcess); - CloseHandle(processInfo.hThread); - } - { - STARTUPINFOA startupInfo; - startupInfo.cb = sizeof(startupInfo); - PROCESS_INFORMATION processInfo; - memset(&startupInfo,0,sizeof(STARTUPINFOA)); - memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); - if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" enable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) { - RegCloseKey(nwAdapters); - throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon); + { + STARTUPINFOA startupInfo; + startupInfo.cb = sizeof(startupInfo); + if (devconLog != INVALID_HANDLE_VALUE) { + startupInfo.hStdOutput = devconLog; + startupInfo.hStdError = devconLog; + } + PROCESS_INFORMATION processInfo; + memset(&startupInfo,0,sizeof(STARTUPINFOA)); + memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); + if (!CreateProcessA(NULL,(LPSTR)(std::string("\"") + _r->homePath + devcon + "\" enable @" + _myDeviceInstanceIdPath).c_str(),NULL,NULL,FALSE,0,NULL,NULL,&startupInfo,&processInfo)) { + RegCloseKey(nwAdapters); + if (devconLog != INVALID_HANDLE_VALUE) + CloseHandle(devconLog); + throw std::runtime_error(std::string("unable to find or execute devcon at ")+devcon); + } + WaitForSingleObject(processInfo.hProcess,INFINITE); + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); } - WaitForSingleObject(processInfo.hProcess,INFINITE); - CloseHandle(processInfo.hProcess); - CloseHandle(processInfo.hThread); + if (devconLog != INVALID_HANDLE_VALUE) + CloseHandle(devconLog); } // Open the tap, which is in this weird Windows analog of /dev @@ -1314,6 +1343,7 @@ EthernetTap::~EthernetTap() ReleaseSemaphore(_injectSemaphore,1,NULL); Thread::join(_thread); + CloseHandle(_tap); CloseHandle(_tapOvlRead.hEvent); CloseHandle(_tapOvlWrite.hEvent); @@ -1329,8 +1359,14 @@ EthernetTap::~EthernetTap() #endif // Disable network device on shutdown + HANDLE devconLog = CreateFileA((_r->homePath + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); STARTUPINFOA startupInfo; startupInfo.cb = sizeof(startupInfo); + if (devconLog != INVALID_HANDLE_VALUE) { + SetFilePointer(devconLog,0,0,FILE_END); + startupInfo.hStdOutput = devconLog; + startupInfo.hStdError = devconLog; + } PROCESS_INFORMATION processInfo; memset(&startupInfo,0,sizeof(STARTUPINFOA)); memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); @@ -1339,6 +1375,8 @@ EthernetTap::~EthernetTap() CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); } + if (devconLog != INVALID_HANDLE_VALUE) + CloseHandle(devconLog); } void EthernetTap::setDisplayName(const char *dn) @@ -1481,7 +1519,7 @@ void EthernetTap::put(const MAC &from,const MAC &to,unsigned int etherType,const if (!_initialized) return; if (len > (ZT_IF_MTU)) - return; + return; // sanity check { Mutex::Lock _l(_injectPending_m); @@ -1626,8 +1664,14 @@ bool EthernetTap::deletePersistentTapDevice(const RuntimeEnvironment *_r,const c Mutex::Lock _l(_systemTapInitLock); // only one thread may mess with taps at a time, process-wide + HANDLE devconLog = CreateFileA((_r->homePath + "\\devcon.log").c_str(),GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); STARTUPINFOA startupInfo; startupInfo.cb = sizeof(startupInfo); + if (devconLog != INVALID_HANDLE_VALUE) { + SetFilePointer(devconLog,0,0,FILE_END); + startupInfo.hStdOutput = devconLog; + startupInfo.hStdError = devconLog; + } PROCESS_INFORMATION processInfo; memset(&startupInfo,0,sizeof(STARTUPINFOA)); memset(&processInfo,0,sizeof(PROCESS_INFORMATION)); @@ -1635,8 +1679,12 @@ bool EthernetTap::deletePersistentTapDevice(const RuntimeEnvironment *_r,const c WaitForSingleObject(processInfo.hProcess,INFINITE); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); + if (devconLog != INVALID_HANDLE_VALUE) + CloseHandle(devconLog); return true; } + if (devconLog != INVALID_HANDLE_VALUE) + CloseHandle(devconLog); return false; } @@ -1655,55 +1703,50 @@ int EthernetTap::cleanPersistentTapDevices(const RuntimeEnvironment *_r,const st if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",0,KEY_READ|KEY_WRITE,&nwAdapters) != ERROR_SUCCESS) return -1; - for(DWORD subkeyIndex=0;subkeyIndex!=-1;) { + for(DWORD subkeyIndex=0;;++subkeyIndex) { DWORD type; DWORD dataLen; DWORD subkeyNameLen = sizeof(subkeyName); DWORD subkeyClassLen = sizeof(subkeyClass); FILETIME lastWriteTime; - switch (RegEnumKeyExA(nwAdapters,subkeyIndex++,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime)) { - case ERROR_NO_MORE_ITEMS: subkeyIndex = -1; break; - case ERROR_SUCCESS: - type = 0; - dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { - data[dataLen] = '\0'; - if (!strnicmp(data,"zttap",5)) { - std::string instanceIdPath; + if (RegEnumKeyExA(nwAdapters,subkeyIndex,subkeyName,&subkeyNameLen,(DWORD *)0,subkeyClass,&subkeyClassLen,&lastWriteTime) == ERROR_SUCCESS) { + type = 0; + dataLen = sizeof(data); + if (RegGetValueA(nwAdapters,subkeyName,"ComponentId",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { + data[dataLen] = '\0'; + if (!strnicmp(data,"zttap",5)) { + std::string instanceIdPath; + type = 0; + dataLen = sizeof(data); + if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) + instanceIdPath.assign(data,dataLen); + if (instanceIdPath.length() != 0) { type = 0; dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"DeviceInstanceID",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) - instanceIdPath.assign(data,dataLen); - if (instanceIdPath.length() != 0) { - type = 0; - dataLen = sizeof(data); - if (RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { - if (dataLen <= 0) { - if (alsoRemoveUnassociatedDevices) - instanceIdPathsToRemove.insert(instanceIdPath); - } else { - if (!exceptThese.count(std::string(data,dataLen))) - instanceIdPathsToRemove.insert(instanceIdPath); - } - } else if (alsoRemoveUnassociatedDevices) - instanceIdPathsToRemove.insert(instanceIdPath); - } + if (RegGetValueA(nwAdapters,subkeyName,"_ZeroTierTapIdentifier",RRF_RT_ANY,&type,(PVOID)data,&dataLen) == ERROR_SUCCESS) { + if (dataLen <= 0) { + if (alsoRemoveUnassociatedDevices) + instanceIdPathsToRemove.insert(instanceIdPath); + } else { + if (!exceptThese.count(std::string(data,dataLen))) + instanceIdPathsToRemove.insert(instanceIdPath); + } + } else if (alsoRemoveUnassociatedDevices) + instanceIdPathsToRemove.insert(instanceIdPath); } } - break; - } + } + } else break; // end of list or failure } RegCloseKey(nwAdapters); } int removed = 0; - for(std::set<std::string>::iterator iidp(instanceIdPathsToRemove.begin());iidp!=instanceIdPathsToRemove.end();++iidp) { if (deletePersistentTapDevice(_r,iidp->c_str())) ++removed; } - return removed; } |