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 <shane.kearns@accenture.com>
This commit is contained in:
Thierry 2012-03-28 20:09:20 +02:00 committed by Qt by Nokia
parent 45b7b0599c
commit aad60ec536

View File

@ -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<LPENUM_SERVICE_STATUS_PROCESS>(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) {