From aad60ec53683e057c05ff760200a467e844cfba3 Mon Sep 17 00:00:00 2001 From: Thierry Date: Wed, 28 Mar 2012 20:09:20 +0200 Subject: Fixes a problem with the proxy detection on Windows The current scheme is to use IE's default config. If that fails get the winhttp config. That's ok. The problem is that if you run a program as a service getting the IE config will set the fAutoDetect flag. But later the call to WinHttpGetProxyForUrl mightfail with the error code ERROR_WINHTTP_AUTODETECTION_FAILED. this patch just makes sure that we have a fallback winhttp solution in case the IE proxy is not set. The new code detcted if the current process is a service, in which case it will try to default to the system-wide proxy. Change-Id: I57e9082a46a8422c54f8f069715752c271a3a001 Reviewed-by: Shane Kearns --- src/network/kernel/qnetworkproxy_win.cpp | 48 ++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp index 4f1dece4a9..a17f547742 100644 --- a/src/network/kernel/qnetworkproxy_win.cpp +++ b/src/network/kernel/qnetworkproxy_win.cpp @@ -113,13 +113,49 @@ typedef HINTERNET (WINAPI * PtrWinHttpOpen)(LPCWSTR, DWORD, LPCWSTR, LPCWSTR,DWO typedef BOOL (WINAPI * PtrWinHttpGetDefaultProxyConfiguration)(WINHTTP_PROXY_INFO*); typedef BOOL (WINAPI * PtrWinHttpGetIEProxyConfigForCurrentUser)(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG*); typedef BOOL (WINAPI * PtrWinHttpCloseHandle)(HINTERNET); +typedef SC_HANDLE (WINAPI * PtrOpenSCManager)(LPCWSTR lpMachineName, LPCWSTR lpDatabaseName, DWORD dwDesiredAccess); +typedef BOOL (WINAPI * PtrEnumServicesStatusEx)(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType, DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName); +typedef BOOL (WINAPI * PtrCloseServiceHandle)(SC_HANDLE hSCObject); static PtrWinHttpGetProxyForUrl ptrWinHttpGetProxyForUrl = 0; static PtrWinHttpOpen ptrWinHttpOpen = 0; static PtrWinHttpGetDefaultProxyConfiguration ptrWinHttpGetDefaultProxyConfiguration = 0; static PtrWinHttpGetIEProxyConfigForCurrentUser ptrWinHttpGetIEProxyConfigForCurrentUser = 0; static PtrWinHttpCloseHandle ptrWinHttpCloseHandle = 0; +static PtrOpenSCManager ptrOpenSCManager = 0; +static PtrEnumServicesStatusEx ptrEnumServicesStatusEx = 0; +static PtrCloseServiceHandle ptrCloseServiceHandle = 0; +static bool currentProcessIsService() +{ + if (!ptrOpenSCManager || !ptrEnumServicesStatusEx|| !ptrCloseServiceHandle) + return false; + + SC_HANDLE hSCM = ptrOpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT); + if (!hSCM) + return false; + + ULONG bufSize = 0; + ULONG nbServices = 0; + if (ptrEnumServicesStatusEx(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, 0, bufSize, &bufSize, &nbServices, 0, 0)) + return false; //error case + + LPENUM_SERVICE_STATUS_PROCESS info = reinterpret_cast(malloc(bufSize)); + bool foundService = false; + if (ptrEnumServicesStatusEx(hSCM, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, (LPBYTE)info, bufSize, &bufSize, &nbServices, 0, 0)) { + DWORD currProcId = GetCurrentProcessId(); + for (ULONG i = 0; i < nbServices && !foundService; i++) { + if (info[i].ServiceStatusProcess.dwProcessId == currProcId) + foundService = true; + } + } + + ptrCloseServiceHandle(hSCM); + free(info); + return foundService; +} + static QStringList splitSpaceSemicolon(const QString &source) { QStringList list; @@ -364,10 +400,14 @@ void QWindowsSystemProxy::init() ptrWinHttpGetProxyForUrl = (PtrWinHttpGetProxyForUrl)lib.resolve("WinHttpGetProxyForUrl"); ptrWinHttpGetDefaultProxyConfiguration = (PtrWinHttpGetDefaultProxyConfiguration)lib.resolve("WinHttpGetDefaultProxyConfiguration"); ptrWinHttpGetIEProxyConfigForCurrentUser = (PtrWinHttpGetIEProxyConfigForCurrentUser)lib.resolve("WinHttpGetIEProxyConfigForCurrentUser"); + ptrOpenSCManager = (PtrOpenSCManager) QSystemLibrary(L"advapi32").resolve("OpenSCManagerW"); + ptrEnumServicesStatusEx = (PtrEnumServicesStatusEx) QSystemLibrary(L"advapi32").resolve("EnumServicesStatusExW"); + ptrCloseServiceHandle = (PtrCloseServiceHandle) QSystemLibrary(L"advapi32").resolve("CloseServiceHandle"); // Try to obtain the Internet Explorer configuration. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyConfig; - if (ptrWinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig)) { + const bool hasIEConfig = ptrWinHttpGetIEProxyConfigForCurrentUser(&ieProxyConfig); + if (hasIEConfig) { if (ieProxyConfig.lpszAutoConfigUrl) { autoConfigUrl = QString::fromWCharArray(ieProxyConfig.lpszAutoConfigUrl); GlobalFree(ieProxyConfig.lpszAutoConfigUrl); @@ -383,9 +423,13 @@ void QWindowsSystemProxy::init() proxyBypass = splitSpaceSemicolon(QString::fromWCharArray(ieProxyConfig.lpszProxyBypass)); GlobalFree(ieProxyConfig.lpszProxyBypass); } - } else { + } + + if (!hasIEConfig || + (currentProcessIsService() && proxyServerList.isEmpty() && proxyBypass.isEmpty())) { // no user configuration // attempt to get the default configuration instead + // that config will serve as default if WPAD fails WINHTTP_PROXY_INFO proxyInfo; if (ptrWinHttpGetDefaultProxyConfiguration(&proxyInfo) && proxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY) { -- cgit v1.2.3