diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c index 2ee3201dd86..842168db60d 100644 --- a/dlls/wininet/internet.c +++ b/dlls/wininet/internet.c @@ -319,6 +319,48 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return TRUE; } +/*********************************************************************** + * INTERNET_SaveProxySettings + * + * Stores the proxy settings given by lpwai into the registry + * + * RETURNS + * ERROR_SUCCESS if no error, or error code on fail + */ +static LONG INTERNET_SaveProxySettings( proxyinfo_t *lpwpi ) +{ + HKEY key; + LONG ret; + + if ((ret = RegOpenKeyW( HKEY_CURRENT_USER, szInternetSettings, &key ))) + return ret; + + if ((ret = RegSetValueExW( key, szProxyEnable, 0, REG_DWORD, (BYTE*)&lpwpi->dwProxyEnabled, sizeof(DWORD)))) + { + RegCloseKey( key ); + return ret; + } + + if (lpwpi->lpszProxyServer) + { + if ((ret = RegSetValueExW( key, szProxyServer, 0, REG_SZ, (BYTE*)lpwpi->lpszProxyServer, sizeof(WCHAR) * (lstrlenW(lpwpi->lpszProxyServer) + 1)))) + { + RegCloseKey( key ); + return ret; + } + } + else + { + if ((ret = RegDeleteValueW( key, szProxyServer ))) + { + RegCloseKey( key ); + return ret; + } + } + + RegCloseKey(key); + return ERROR_SUCCESS; +} /*********************************************************************** * InternetInitializeAutoProxyDll (WININET.@) @@ -2458,6 +2500,49 @@ BOOL WINAPI InternetSetOptionW(HINTERNET hInternet, DWORD dwOption, SetLastError(ERROR_INVALID_PARAMETER); ret = FALSE; break; + case INTERNET_OPTION_PER_CONNECTION_OPTION: { + INTERNET_PER_CONN_OPTION_LISTW *con = lpBuffer; + LONG res; + int i; + proxyinfo_t pi; + + INTERNET_LoadProxySettings(&pi); + + for (i = 0; i < con->dwOptionCount; i++) { + INTERNET_PER_CONN_OPTIONW *option = con->pOptions + i; + + switch (option->dwOption) { + case INTERNET_PER_CONN_PROXY_SERVER: + HeapFree(GetProcessHeap(), 0, pi.lpszProxyServer); + pi.lpszProxyServer = heap_strdupW(option->Value.pszValue); + break; + + case INTERNET_PER_CONN_FLAGS: + case INTERNET_PER_CONN_AUTOCONFIG_URL: + case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS: + case INTERNET_PER_CONN_AUTOCONFIG_SECONDARY_URL: + case INTERNET_PER_CONN_AUTOCONFIG_RELOAD_DELAY_MINS: + case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_TIME: + case INTERNET_PER_CONN_AUTOCONFIG_LAST_DETECT_URL: + case INTERNET_PER_CONN_PROXY_BYPASS: + FIXME("Unhandled dwOption %d\n", option->dwOption); + break; + + default: + FIXME("Unknown dwOption %d\n", option->dwOption); + SetLastError(ERROR_INVALID_PARAMETER); + break; + } + } + + if ((res = INTERNET_SaveProxySettings(&pi))) + SetLastError(res); + + FreeProxyInfo(&pi); + + ret = (res == ERROR_SUCCESS); + break; + } default: FIXME("Option %d STUB\n",dwOption); SetLastError(ERROR_INTERNET_INVALID_OPTION); diff --git a/dlls/wininet/tests/internet.c b/dlls/wininet/tests/internet.c index 8708878b7c4..2dc1fd90e74 100644 --- a/dlls/wininet/tests/internet.c +++ b/dlls/wininet/tests/internet.c @@ -848,6 +848,123 @@ static void test_Option_Policy(void) ok(ret == TRUE, "InternetCloseHandle failed: 0x%08x\n", GetLastError()); } +static void test_Option_PerConnectionOption(void) +{ + BOOL ret; + DWORD size = sizeof(INTERNET_PER_CONN_OPTION_LISTW); + INTERNET_PER_CONN_OPTION_LISTW list = {size}; + INTERNET_PER_CONN_OPTIONW *orig_settings; + static WCHAR proxy_srvW[] = {'p','r','o','x','y','.','e','x','a','m','p','l','e',0}; + + /* get the global IE proxy server info, to restore later */ + list.dwOptionCount = 1; + list.pOptions = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNET_PER_CONN_OPTIONW)); + + list.pOptions[0].dwOption = INTERNET_PER_CONN_PROXY_SERVER; + + ret = InternetQueryOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, + &list, &size); + ok(ret == TRUE, "InternetQueryOption should've succeeded\n"); + orig_settings = list.pOptions; + + /* set the global IE proxy server */ + list.dwOptionCount = 1; + list.pOptions = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNET_PER_CONN_OPTIONW)); + + list.pOptions[0].dwOption = INTERNET_PER_CONN_PROXY_SERVER; + list.pOptions[0].Value.pszValue = proxy_srvW; + + ret = InternetSetOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, + &list, size); + ok(ret == TRUE, "InternetSetOption should've succeeded\n"); + + HeapFree(GetProcessHeap(), 0, list.pOptions); + + /* get & verify the global IE proxy server */ + list.dwOptionCount = 1; + list.dwOptionError = 0; + list.pOptions = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNET_PER_CONN_OPTIONW)); + + list.pOptions[0].dwOption = INTERNET_PER_CONN_PROXY_SERVER; + + ret = InternetQueryOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, + &list, &size); + ok(ret == TRUE, "InternetQueryOption should've succeeded\n"); + ok(!lstrcmpW(list.pOptions[0].Value.pszValue, proxy_srvW), + "Retrieved proxy server should've been %s, was: %s\n", + wine_dbgstr_w(proxy_srvW), wine_dbgstr_w(list.pOptions[0].Value.pszValue)); + + HeapFree(GetProcessHeap(), 0, list.pOptions); + + /* restore original settings */ + list.dwOptionCount = 1; + list.pOptions = orig_settings; + + ret = InternetSetOptionW(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, + &list, size); + ok(ret == TRUE, "InternetSetOption should've succeeded\n"); + + HeapFree(GetProcessHeap(), 0, list.pOptions); +} + +static void test_Option_PerConnectionOptionA(void) +{ + BOOL ret; + DWORD size = sizeof(INTERNET_PER_CONN_OPTION_LISTA); + INTERNET_PER_CONN_OPTION_LISTA list = {size}; + INTERNET_PER_CONN_OPTIONA *orig_settings; + char proxy_srv[] = "proxy.example"; + + /* get the global IE proxy server info, to restore later */ + list.dwOptionCount = 1; + list.pOptions = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNET_PER_CONN_OPTIONA)); + + list.pOptions[0].dwOption = INTERNET_PER_CONN_PROXY_SERVER; + + ret = InternetQueryOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, + &list, &size); + ok(ret == TRUE, "InternetQueryOption should've succeeded\n"); + orig_settings = list.pOptions; + + /* set the global IE proxy server */ + list.dwOptionCount = 1; + list.pOptions = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNET_PER_CONN_OPTIONA)); + + list.pOptions[0].dwOption = INTERNET_PER_CONN_PROXY_SERVER; + list.pOptions[0].Value.pszValue = proxy_srv; + + ret = InternetSetOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, + &list, size); + ok(ret == TRUE, "InternetSetOption should've succeeded\n"); + + HeapFree(GetProcessHeap(), 0, list.pOptions); + + /* get & verify the global IE proxy server */ + list.dwOptionCount = 1; + list.dwOptionError = 0; + list.pOptions = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNET_PER_CONN_OPTIONA)); + + list.pOptions[0].dwOption = INTERNET_PER_CONN_PROXY_SERVER; + + ret = InternetQueryOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, + &list, &size); + ok(ret == TRUE, "InternetQueryOption should've succeeded\n"); + ok(!lstrcmpA(list.pOptions[0].Value.pszValue, "proxy.example"), + "Retrieved proxy server should've been \"%s\", was: \"%s\"\n", + proxy_srv, list.pOptions[0].Value.pszValue); + + HeapFree(GetProcessHeap(), 0, list.pOptions); + + /* restore original settings */ + list.dwOptionCount = 1; + list.pOptions = orig_settings; + + ret = InternetSetOptionA(NULL, INTERNET_OPTION_PER_CONNECTION_OPTION, + &list, size); + ok(ret == TRUE, "InternetSetOption should've succeeded\n"); + + HeapFree(GetProcessHeap(), 0, list.pOptions); +} /* ############################### */ @@ -872,6 +989,8 @@ START_TEST(internet) test_version(); test_null(); test_Option_Policy(); + test_Option_PerConnectionOption(); + test_Option_PerConnectionOptionA(); if (!pInternetTimeFromSystemTimeA) win_skip("skipping the InternetTime tests\n");