diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2012-03-08 16:02:44 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2012-03-08 16:02:44 +0000 |
commit | 3e25449aa5943de83fc5547f94cb8024552f4c2e (patch) | |
tree | 5db7b76944c2b9d8260ce7f13d27b0ccd272e2da /winsup/cygwin/net.cc | |
parent | efb1f061f10c50410ede9401ccddaf93240f8335 (diff) | |
download | newlib-3e25449aa5943de83fc5547f94cb8024552f4c2e.zip newlib-3e25449aa5943de83fc5547f94cb8024552f4c2e.tar.gz newlib-3e25449aa5943de83fc5547f94cb8024552f4c2e.tar.bz2 |
* net.cc (call_gaa): New thread function to call GetAdaptersAddresses.
(get_adapters_addresses): Call call_gaa. If necessary, call it as
child thread. Explain why that's necessary.
Diffstat (limited to 'winsup/cygwin/net.cc')
-rw-r--r-- | winsup/cygwin/net.cc | 65 |
1 files changed, 50 insertions, 15 deletions
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 40ab47b..830a800 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -1650,36 +1650,71 @@ ip_addr_prefix (PIP_ADAPTER_UNICAST_ADDRESS pua, PIP_ADAPTER_PREFIX pap) #define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100 #endif -bool -get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family) +struct gaa_wa { + ULONG family; + PIP_ADAPTER_ADDRESSES *pa_ret; +}; + +DWORD WINAPI +call_gaa (LPVOID param) { DWORD ret, size = 0; + gaa_wa *p = (gaa_wa *) param; PIP_ADAPTER_ADDRESSES pa0 = NULL; - if (!pa_ret) - return ERROR_BUFFER_OVERFLOW - == GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX + if (!p->pa_ret) + return GetAdaptersAddresses (p->family, GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_ALL_INTERFACES, - NULL, NULL, &size); + NULL, NULL, &size); do { - ret = GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX - | GAA_FLAG_INCLUDE_ALL_INTERFACES, + ret = GetAdaptersAddresses (p->family, GAA_FLAG_INCLUDE_PREFIX + | GAA_FLAG_INCLUDE_ALL_INTERFACES, NULL, pa0, &size); if (ret == ERROR_BUFFER_OVERFLOW && !(pa0 = (PIP_ADAPTER_ADDRESSES) realloc (pa0, size))) break; } while (ret == ERROR_BUFFER_OVERFLOW); - if (ret != ERROR_SUCCESS) + if (pa0) { - if (pa0) - free (pa0); - *pa_ret = NULL; - return false; + if (ret != ERROR_SUCCESS) + { + free (pa0); + *p->pa_ret = pa0; + } + else + *p->pa_ret = pa0; } - *pa_ret = pa0; - return true; + return ret; +} + +bool +get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family) +{ + DWORD ret; + gaa_wa param = { family, pa_ret ?: NULL }; + + if ((uintptr_t) ¶m >= (uintptr_t) 0x80000000L) + { + /* Starting with Windows Vista, GetAdaptersAddresses fails with error 998, + if it's running in a thread with a stack located in the large address + area. So, if we're running in a pthread with such a stack, we call + GetAdaptersAddresses in a child thread with an OS-allocated stack, + which is guaranteed to be located in the lower address area. */ + HANDLE thr = CreateThread (NULL, 0, call_gaa, ¶m, 0, NULL); + if (!thr) + { + debug_printf ("CreateThread: %E"); + return false; + } + WaitForSingleObject (thr, INFINITE); + GetExitCodeThread (thr, &ret); + CloseHandle (thr); + } + else + ret = call_gaa (¶m); + return ret == ERROR_SUCCESS || (!pa_ret && ret == ERROR_BUFFER_OVERFLOW); } #define WS_IFF_UP 1 |