Module: wine Branch: master Commit: 0ad36ed3e7d2c6955e76fb3a7fab1c1946a9f2ac URL: https://gitlab.winehq.org/wine/wine/-/commit/0ad36ed3e7d2c6955e76fb3a7fab1c1...
Author: Gabriel Ivăncescu gabrielopcode@gmail.com Date: Tue Oct 18 19:40:05 2022 +0300
wininet: Handle offline state in InternetGetConnectedStateExW.
Some applications (e.g. Deus Ex Human Revolution: Director's Cut) use the output from this function to determine whether they should connect.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com
---
dlls/wininet/internet.c | 59 +++++++++++++++++++++++++++++++++++++++---- dlls/wininet/tests/internet.c | 9 +++++-- 2 files changed, 61 insertions(+), 7 deletions(-)
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 120cc9af4cc..292fd44dd8e 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -1206,24 +1206,73 @@ BOOL WINAPI InternetGetConnectedState(LPDWORD lpdwStatus, DWORD dwReserved) BOOL WINAPI InternetGetConnectedStateExW(LPDWORD lpdwStatus, LPWSTR lpszConnectionName, DWORD dwNameLen, DWORD dwReserved) { + IP_ADAPTER_ADDRESSES *buf = NULL, *aa; + ULONG size = 0; + DWORD status; + TRACE("(%p, %p, %ld, 0x%08lx)\n", lpdwStatus, lpszConnectionName, dwNameLen, dwReserved);
/* Must be zero */ if(dwReserved) return FALSE;
- if (lpdwStatus) { - WARN("always returning LAN connection and RAS installed.\n"); - *lpdwStatus = INTERNET_CONNECTION_LAN | INTERNET_RAS_INSTALLED; + for (;;) + { + ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_INCLUDE_ALL_GATEWAYS; + ULONG errcode = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, buf, &size); + + if (errcode == ERROR_SUCCESS) + break; + heap_free(buf); + if (errcode == ERROR_BUFFER_OVERFLOW && !(buf = heap_alloc(size))) + errcode = ERROR_NOT_ENOUGH_MEMORY; + if (errcode != ERROR_BUFFER_OVERFLOW) + { + if (errcode != ERROR_NO_DATA) + { + SetLastError(errcode); + return FALSE; + } + buf = NULL; + break; + } + } + + status = INTERNET_RAS_INSTALLED; + for (aa = buf; aa; aa = aa->Next) + { + /* Connected, but not necessarily to internet */ + if (aa->FirstUnicastAddress) + status |= INTERNET_CONNECTION_OFFLINE; + + /* Connected to internet */ + if (aa->FirstGatewayAddress) + { + WARN("always returning LAN connection.\n"); + status &= ~INTERNET_CONNECTION_OFFLINE; + status |= INTERNET_CONNECTION_LAN; + break; + } } + heap_free(buf); + + if (lpdwStatus) *lpdwStatus = status;
/* When the buffer size is zero LoadStringW fills the buffer with a pointer to * the resource, avoid it as we must not change the buffer in this case */ - if(lpszConnectionName && dwNameLen) { + if (lpszConnectionName && dwNameLen) + { *lpszConnectionName = '\0'; - LoadStringW(WININET_hModule, IDS_LANCONNECTION, lpszConnectionName, dwNameLen); + if (status & INTERNET_CONNECTION_LAN) + LoadStringW(WININET_hModule, IDS_LANCONNECTION, lpszConnectionName, dwNameLen); }
+ if (!(status & (INTERNET_CONNECTION_LAN | INTERNET_CONNECTION_MODEM | INTERNET_CONNECTION_PROXY))) + { + SetLastError(ERROR_SUCCESS); + return FALSE; + } return TRUE; }
diff --git a/dlls/wininet/tests/internet.c b/dlls/wininet/tests/internet.c index 97bd36f9427..0d58a12558e 100644 --- a/dlls/wininet/tests/internet.c +++ b/dlls/wininet/tests/internet.c @@ -1730,12 +1730,17 @@ static void test_InternetGetConnectedStateExW(void) }
flags = 0; - buffer[0] = 0; + wcscpy(buffer, L"wine"); + SetLastError(0xdeadbeef); res = pInternetGetConnectedStateExW(&flags, buffer, ARRAY_SIZE(buffer), 0); trace("Internet Connection: Flags 0x%02lx - Name '%s'\n", flags, wine_dbgstr_w(buffer)); ok (flags & INTERNET_RAS_INSTALLED, "Missing RAS flag\n"); if(!res) { - win_skip("InternetGetConnectedStateExW tests require a valid connection\n"); + DWORD error = GetLastError(); + ok(error == ERROR_SUCCESS, "Last error = %#lx\n", error); + ok(!buffer[0], "Expected empty connection name, got %s\n", wine_dbgstr_w(buffer)); + + skip("InternetGetConnectedStateExW tests require a valid connection\n"); return; }