Fixes Marvel Snap being unable to connect to servers (part of it, another part is wmic patches), and maybe improves wait times in many other apps.
Typically "http://wpad/..." (which is commonly requested as lpszAutoConfigUrl for WinHttpGetProxyForUrl) is not available and WinHttpGetProxyForUrl() is hanging for a really long time resolving this name in download_script().
On Windows 10 here the name resolution timeout is about 9sec (and I could not find a way to configure it for a longer timeout). On Linux default DNS timeouts are typically longer. Yet, while WinHttpGetProxyForUrl() execution time is not consistent here, when I run it right after reboot or after network interface reconnection it typically takes ~4-7 seconds to complete on the first run. Then, testing it again shortly after yields no noticeable timeout. I suppose Windows caches and manages that globally in some service, so maximum possible 9 seconds name resolution timeout is rarely hit. Since proxy config URL, if available, is supposed to be in the local network, having the timeout of 5 seconds for name resolution looks more than enough to me.
-- v2: winhttp: Cache script in download_script(). winhttp: Set name resolution timeout in download_script().
From: Paul Gofman pgofman@codeweavers.com
--- dlls/winhttp/session.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index fa8ccd7a9de..3d99e9b0ac6 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -1922,6 +1922,7 @@ static char *download_script( const WCHAR *url, DWORD *out_size ) hostname[uc.dwHostNameLength] = 0;
if (!(ses = WinHttpOpen( NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 ))) goto done; + WinHttpSetTimeouts( ses, 5000, 60000, 30000, 30000 ); if (!(con = WinHttpConnect( ses, hostname, uc.nPort, 0 ))) goto done; if (uc.nScheme == INTERNET_SCHEME_HTTPS) flags |= WINHTTP_FLAG_SECURE; if (!(req = WinHttpOpenRequest( con, NULL, uc.lpszUrlPath, NULL, NULL, acceptW, flags ))) goto done;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/winhttp/session.c | 54 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-)
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 3d99e9b0ac6..8aa99f0ece7 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -1901,6 +1901,50 @@ static BOOL parse_script_result( const char *result, WINHTTP_PROXY_INFO *info ) return TRUE; }
+static SRWLOCK cache_lock = SRWLOCK_INIT; +static DWORD cached_script_size; +static ULONGLONG cache_update_time; +static char *cached_script; +static WCHAR *cached_url; + +static BOOL get_cached_script( const WCHAR *url, char **buffer, DWORD *out_size ) +{ + BOOL ret = FALSE; + + *buffer = NULL; + *out_size = 0; + + AcquireSRWLockExclusive( &cache_lock ); + if (cached_url && !wcscmp( cached_url, url ) && GetTickCount64() - cache_update_time < 60000) + { + ret = TRUE; + if (cached_script && (*buffer = malloc( cached_script_size ))) + { + memcpy( *buffer, cached_script, cached_script_size ); + *out_size = cached_script_size; + } + } + ReleaseSRWLockExclusive( &cache_lock ); + return ret; +} + +static void cache_script( const WCHAR *url, char *buffer, DWORD size ) +{ + AcquireSRWLockExclusive( &cache_lock ); + free( cached_url ); + free( cached_script ); + cached_script_size = 0; + cached_script = NULL; + + if ((cached_url = wcsdup( url )) && buffer && (cached_script = malloc( size ))) + { + memcpy( cached_script, buffer, size ); + cached_script_size = size; + } + cache_update_time = GetTickCount64(); + ReleaseSRWLockExclusive( &cache_lock ); +} + static char *download_script( const WCHAR *url, DWORD *out_size ) { static const WCHAR *acceptW[] = {L"*/*", NULL}; @@ -1908,9 +1952,14 @@ static char *download_script( const WCHAR *url, DWORD *out_size ) WCHAR *hostname; URL_COMPONENTSW uc; DWORD status, size = sizeof(status), offset, to_read, bytes_read, flags = 0; - char *tmp, *buffer = NULL; + char *tmp, *buffer;
- *out_size = 0; + if (get_cached_script( url, &buffer, out_size )) + { + TRACE( "Returning cached result.\n" ); + if (!buffer) SetLastError( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT ); + return buffer; + }
memset( &uc, 0, sizeof(uc) ); uc.dwStructSize = sizeof(uc); @@ -1957,6 +2006,7 @@ done: WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); free( hostname ); + cache_script( url, buffer, *out_size ); if (!buffer) SetLastError( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT ); return buffer; }
v2: - Use helper functions for cache access; - Use GetTickCount64() instead of GetTickCount(); - Check for wcsdup() failure.
This merge request was approved by Hans Leidekker.