Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

GH #328: NetworkInterface on Windows XP

  • Loading branch information...
commit ceef0c64ade13a878d2a5933e9dbe5a7c4a5fab8 1 parent 8cbaa4e
@aleks-f aleks-f authored
View
2  CHANGELOG
@@ -64,6 +64,8 @@ Release 1.5.3 (2014-05-xx)
- fixed GH #321: trivial build fixes (BB QNX build)
- fixed GH #440: MongoDB ObjectId string formatting
- added SevenZip library (Guenter Obiltschnig)
+- fixed GH #442: Use correct prefix length field of Windows IP_ADAPTER_PREFIX structure
+- improved GH #328: NetworkInterface on Windows XP
Release 1.5.2 (2013-09-16)
==========================
View
44 Foundation/include/Poco/Platform_WIN32.h
@@ -24,31 +24,55 @@
#include "Poco/UnWindows.h"
-// determine the real version
-#if defined(_WIN32_WINNT_WIN8)
+// Determine the real version.
+// This setting can be forced from UnWindows.h
+#if defined (_WIN32_WINNT_WINBLUE)
+ //Windows 8.1 _WIN32_WINNT_WINBLUE (0x0602)
+ #ifdef _WIN32_WINNT
+ #undef _WIN32_WINNT
+ #endif
+ #define _WIN32_WINNT _WIN32_WINNT_WINBLUE
+ #ifdef NTDDI_VERSION
+ #undef NTDDI_VERSION
+ #endif
+ #define NTDDI_VERSION NTDDI_WINBLUE
+#elif defined (_WIN32_WINNT_WIN8)
//Windows 8 _WIN32_WINNT_WIN8 (0x0602)
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_WIN8
-#elif defined(_WIN32_WINNT_WIN7)
+ #ifdef NTDDI_VERSION
+ #undef NTDDI_VERSION
+ #endif
+ #define NTDDI_VERSION NTDDI_WIN8
+#elif defined (_WIN32_WINNT_WIN7)
//Windows 7 _WIN32_WINNT_WIN7 (0x0601)
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_WIN7
+ #ifndef NTDDI_VERSION
+ #define NTDDI_VERSION NTDDI_WIN7
+ #endif
#elif defined (_WIN32_WINNT_WS08)
//Windows Server 2008 _WIN32_WINNT_WS08 (0x0600)
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_WS08
+ #ifndef NTDDI_VERSION
+ #define NTDDI_VERSION NTDDI_WS08
+ #endif
#elif defined (_WIN32_WINNT_VISTA)
//Windows Vista _WIN32_WINNT_VISTA (0x0600)
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_VISTA
+ #ifndef NTDDI_VERSION
+ #define NTDDI_VERSION NTDDI_VISTA
+ #endif
#elif defined (_WIN32_WINNT_LONGHORN)
//Windows Vista and server 2008 Development _WIN32_WINNT_LONGHORN (0x0600)
#ifdef _WIN32_WINNT
@@ -62,12 +86,18 @@
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_WS03
+ #ifndef NTDDI_VERSION
+ #define NTDDI_VERSION NTDDI_WS03
+ #endif
#elif defined (_WIN32_WINNT_WINXP)
//Windows Server 2003, Windows XP _WIN32_WINNT_WINXP (0x0501)
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_WINXP
+ #ifndef NTDDI_VERSION
+ #define NTDDI_VERSION NTDDI_WINXP
+ #endif
#elif defined (_WIN32_WINNT_WIN2K)
//Windows 2000 _WIN32_WINNT_WIN2K (0x0500)
#ifdef _WIN32_WINNT
@@ -75,10 +105,18 @@
#endif
#define _WIN32_WINNT _WIN32_WINNT_WIN2K
#elif defined (WINVER)
+ // fail back on WINVER
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT WINVER
+#elif !defined(_WIN32_WINNT)
+ // last resort = Win XP, SP1 is minimum supported
+ #define _WIN32_WINNT 0x0501
+ #ifdef NTDDI_VERSION
+ #undef NTDDI_VERSION
+ #endif
+ #define NTDDI_VERSION 0x05010100
#endif
View
20 Foundation/include/Poco/UnWindows.h
@@ -47,11 +47,29 @@
#endif
+// Microsoft Visual C++ includes copies of the Windows header files
+// that were current at the time Visual C++ was released.
+// The Windows header files use macros to indicate which versions
+// of Windows support many programming elements. Therefore, you must
+// define these macros to use new functionality introduced in each
+// major operating system release. (Individual header files may use
+// different macros; therefore, if compilation problems occur, check
+// the header file that contains the definition for conditional
+// definitions.) For more information, see SdkDdkVer.h.
+
#if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0501)
#error Unsupported Windows version.
+#elif defined(NTDDI_VERSION) && (NTDDI_VERSION < 0x05010100)
+ #error Unsupported Windows version.
#elif !defined(_WIN32_WINNT)
- // define minimum supported
+ // Define minimum supported version.
+ // This can be changed, if needed.
+ // Otherwise, the Platform_WIN32.h will do
+ // its best to determine the appropriate values
+ // and may redefine these. See Platform_WIN32.h
+ // for details.
#define _WIN32_WINNT 0x0501
+ #define NTDDI_VERSION 0x05010100
#endif
View
10 Net/include/Poco/Net/NetworkInterface.h
@@ -49,6 +49,16 @@ class Net_API NetworkInterface
/// The class also provides static member functions for
/// enumerating or searching network interfaces and their
/// respective configuration values.
+ ///
+ /// On Windows, detection capabilities vary depending on the
+ /// OS version/service pack. Although the best effort is made
+ /// not to attempt access to non-existent features through a
+ /// combination of compile/runtime checks, when running binaries
+ /// compiled on a newer version of the OS on an older one
+ /// problems may occur; if possible, it is best to run
+ /// binaries on the OS version where they were compiled.
+ /// This particularly applies to OS versions older than Vista
+ /// and XP.
{
public:
typedef std::vector<NetworkInterface> List;
View
120 Net/src/NetworkInterface.cpp
@@ -966,11 +966,66 @@ NetworkInterface::Type fromNative(DWORD type)
}
}
+
+IPAddress subnetMaskForInterface(const std::string& name, bool isLoopback)
+{
+ if (isLoopback)
+ {
+ return IPAddress::parse("255.0.0.0");
+ }
+ else
+ {
+ std::string subKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\");
+ subKey += name;
+ std::string netmask;
+ HKEY hKey;
+#if defined(POCO_WIN32_UTF8) && !defined(POCO_NO_WSTRING)
+ std::wstring usubKey;
+ Poco::UnicodeConverter::toUTF16(subKey, usubKey);
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, usubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+ return IPAddress();
+ wchar_t unetmask[16];
+ DWORD size = sizeof(unetmask);
+ if (RegQueryValueExW(hKey, L"DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
+ {
+ if (RegQueryValueExW(hKey, L"SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return IPAddress();
+ }
+ }
+ Poco::UnicodeConverter::toUTF8(unetmask, netmask);
+#else
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+ return IPAddress();
+ char unetmask[16];
+ DWORD size = sizeof(unetmask);
+ if (RegQueryValueExA(hKey, "DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
+ {
+ if (RegQueryValueExA(hKey, "SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return IPAddress();
+ }
+ }
+ netmask = unetmask;
+#endif
+ RegCloseKey(hKey);
+ return IPAddress::parse(netmask);
+ }
+}
+
+
} /// namespace
NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
{
+ OSVERSIONINFO osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osvi);
+
FastMutex::ScopedLock lock(_mutex);
Map result;
ULONG outBufLen = 16384;
@@ -1010,15 +1065,32 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
unsigned ifIndex = 0;
#if defined(POCO_HAVE_IPv6)
- #if (_WIN32_WINNT >= 0x600) && defined (IP_ADAPTER_IPV6_ENABLED)
- if (pAddress->Flags & IP_ADAPTER_IPV6_ENABLED) ifIndex = pAddress->Ipv6IfIndex;
- #else
- ifIndex = pAddress->Ipv6IfIndex;
- #endif
-#endif
-#if (_WIN32_WINNT >= 0x600) && defined (IP_ADAPTER_IPV4_ENABLED)
- if (pAddress->Flags & IP_ADAPTER_IPV4_ENABLED) ifIndex = pAddress->IfIndex;
-#else
+ #if (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1
+ #if defined (IP_ADAPTER_IPV6_ENABLED) // Vista
+ if ((pAddress->Flags & IP_ADAPTER_IPV6_ENABLED) &&
+ (osvi.dwMajorVersion >= 5) &&
+ (osvi.dwMinorVersion >= 1) &&
+ (osvi.dwBuildNumber >=1))
+ {
+ ifIndex = pAddress->Ipv6IfIndex;
+ }
+ #else // !defined(IP_ADAPTER_IPV6_ENABLED)
+ if ((osvi.dwMajorVersion >= 5) &&
+ (osvi.dwMinorVersion >= 1) &&
+ (osvi.dwBuildNumber >= 0))
+ {
+ ifIndex = pAddress->Ipv6IfIndex;
+ }
+ #endif // defined(IP_ADAPTER_IPV6_ENABLED)
+ #endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100)
+#endif // POCO_HAVE_IPv6
+
+#if defined (IP_ADAPTER_IPV4_ENABLED)
+ if (pAddress->Flags & IP_ADAPTER_IPV4_ENABLED)
+ {
+ ifIndex = pAddress->IfIndex;
+ }
+#else // !IP_ADAPTER_IPV4_ENABLED
ifIndex = pAddress->IfIndex;
#endif
if (ifIndex == 0) continue;
@@ -1054,7 +1126,12 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
ifIt->second.impl().setMTU(pAddress->Mtu);
ifIt->second.impl().setUp(pAddress->OperStatus == IfOperStatusUp);
#if (_WIN32_WINNT >= 0x0600) // Vista and newer only
- ifIt->second.impl().setRunning(pAddress->ReceiveLinkSpeed > 0 || pAddress->TransmitLinkSpeed > 0);
+ if ((osvi.dwMajorVersion >= 6) &&
+ (osvi.dwMinorVersion >= 0) &&
+ (osvi.dwBuildNumber >= 0))
+ {
+ ifIt->second.impl().setRunning(pAddress->ReceiveLinkSpeed > 0 || pAddress->TransmitLinkSpeed > 0);
+ }
#endif
ifIt->second.impl().setType(fromNative(pAddress->IfType));
if (pAddress->PhysicalAddressLength)
@@ -1077,10 +1154,11 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
// On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); additionaly, on pre-Vista versions of
// OS, master address structure does not contain member for prefix length; we go an extra mile here in order to make sure
// we reflect the actual values held by system and protect against misconfiguration (e.g. bad DHCP config entry)
-#if (_WIN32_WINNT >= 0x0600) // Vista and newer
+#if (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1
+ #if (_WIN32_WINNT >= 0x0600) // Vista and newer
UINT8 prefixLength = pUniAddr->OnLinkPrefixLength;
broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address);
-#else
+ #else // _WIN32_WINNT < 0x0600
ULONG prefixLength = 0;
broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
// if previous call did not do it, make last-ditch attempt for prefix and broadcast
@@ -1093,8 +1171,22 @@ NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
IPAddress host(mask & address);
broadcastAddress = host | ~mask;
}
-#endif
- subnetMask = prefixLength ? IPAddress(prefixLength, IPAddress::IPv4) : IPAddress();
+ #endif // _WIN32_WINNT >= 0x0600
+#endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100)
+ if (prefixLength)
+ {
+ subnetMask = IPAddress(prefixLength, IPAddress::IPv4);
+ }
+ else // if all of the above fails, look up the subnet mask in the registry
+ {
+ address = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pUniAddr->Address.lpSockaddr)->sin_addr, sizeof(in_addr));
+ subnetMask = subnetMaskForInterface(name, address.isLoopback());
+ if (!address.isLoopback())
+ {
+ broadcastAddress = address;
+ broadcastAddress.mask(subnetMask, IPAddress::broadcast());
+ }
+ }
ifIt->second.addAddress(address, subnetMask, broadcastAddress);
}
else
Please sign in to comment.
Something went wrong with that request. Please try again.