- Timestamp:
- Sep 14, 2015 7:33:23 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/generic/http-curl.cpp
r57737 r57749 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - HTTP c ommunication API.3 * IPRT - HTTP client API, cURL based. 4 4 */ 5 5 … … 39 39 #include <iprt/err.h> 40 40 #include <iprt/file.h> 41 #ifdef RT_OS_WINDOWS 42 # include <iprt/ldr.h> 43 #endif 41 44 #include <iprt/mem.h> 45 #include <iprt/once.h> 42 46 #include <iprt/path.h> 43 47 #include <iprt/stream.h> … … 48 52 49 53 #include <curl/curl.h> 54 55 #ifdef RT_OS_WINDOWS 56 # include <Winhttp.h> 57 #endif 50 58 51 59 … … 126 134 127 135 136 #ifdef RT_OS_WINDOWS 137 /** @name Windows: Types for dynamically resolved APIs 138 * @{ */ 139 typedef HINTERNET (WINAPI * PFNWINHTTPOPEN)(LPCWSTR, DWORD, LPCWSTR, LPCWSTR, DWORD); 140 typedef BOOL (WINAPI * PFNWINHTTPCLOSEHANDLE)(HINTERNET); 141 typedef BOOL (WINAPI * PFNWINHTTPGETPROXYFORURL)(HINTERNET, LPCWSTR, WINHTTP_AUTOPROXY_OPTIONS *, WINHTTP_PROXY_INFO *); 142 typedef BOOL (WINAPI * PFNWINHTTPGETDEFAULTPROXYCONFIGURATION)(WINHTTP_PROXY_INFO *); 143 typedef BOOL (WINAPI * PFNWINHTTPGETIEPROXYCONFIGFORCURRENTUSER)(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *); 144 /** @} */ 145 #endif 146 147 128 148 /********************************************************************************************************************************* 129 149 * Defined Constants And Macros * … … 161 181 AssertReturnVoid((hHttp)->u32Magic == RTHTTP_MAGIC); \ 162 182 } while (0) 183 184 185 /********************************************************************************************************************************* 186 * Global Variables * 187 *********************************************************************************************************************************/ 188 #ifdef RT_OS_WINDOWS 189 /** @name Windows: Dynamically resolved APIs 190 * @{ */ 191 static RTONCE g_WinResolveImportsOnce = RTONCE_INITIALIZER; 192 static RTLDRMOD g_hWinHttpMod = NIL_RTLDRMOD; 193 static PFNWINHTTPOPEN g_pfnWinHttpOpen = NULL; 194 static PFNWINHTTPCLOSEHANDLE g_pfnWinHttpCloseHandle = NULL; 195 static PFNWINHTTPGETPROXYFORURL g_pfnWinHttpGetProxyForUrl = NULL; 196 static PFNWINHTTPGETDEFAULTPROXYCONFIGURATION g_pfnWinHttpGetDefaultProxyConfiguration = NULL; 197 static PFNWINHTTPGETIEPROXYCONFIGFORCURRENTUSER g_pfnWinHttpGetIEProxyConfigForCurrentUser = NULL; 198 /** @} */ 199 #endif 163 200 164 201 … … 670 707 } 671 708 709 #ifdef RT_OS_WINDOWS 710 711 /** 712 * @callback_method_impl{FNRTONCE, Loads WinHttp.dll and resolves APIs} 713 */ 714 static DECLCALLBACK(int) rtHttpWinResolveImports(void *pvUser) 715 { 716 RTLDRMOD hMod; 717 int rc = RTLdrLoadSystem("winhttp.dll", true /*fNoUnload*/, &hMod); 718 if (RT_SUCCESS(rc)) 719 { 720 rc = RTLdrGetSymbol(hMod, "WinHttpOpen", (void **)&g_pfnWinHttpOpen); 721 if (RT_SUCCESS(rc)) 722 rc = RTLdrGetSymbol(hMod, "WinHttpCloseHandle", (void **)&g_pfnWinHttpCloseHandle); 723 if (RT_SUCCESS(rc)) 724 rc = RTLdrGetSymbol(hMod, "WinHttpGetProxyForUrl", (void **)&g_pfnWinHttpGetProxyForUrl); 725 if (RT_SUCCESS(rc)) 726 rc = RTLdrGetSymbol(hMod, "WinHttpGetDefaultProxyConfiguration", (void **)&g_pfnWinHttpGetDefaultProxyConfiguration); 727 if (RT_SUCCESS(rc)) 728 rc = RTLdrGetSymbol(hMod, "WinHttpGetIEProxyConfigForCurrentUser", (void **)&g_pfnWinHttpGetIEProxyConfigForCurrentUser); 729 RTLdrClose(hMod); 730 } 731 AssertRC(rc); 732 733 NOREF(pvUser); 734 return rc; 735 } 736 737 738 /** 739 * Reconfigures the cURL proxy settings for the given URL. 740 * 741 * @returns IPRT status code. VINF_NOT_SUPPORTED if we should try fallback. 742 * @param pThis The HTTP client instance. 743 * @param pszUrl The URL. 744 */ 745 static int rtHttpConfigureProxyForUrlWindows(PRTHTTPINTERNAL pThis, const char *pszUrl) 746 { 747 int rcRet = VINF_NOT_SUPPORTED; 748 749 int rc = RTOnce(&g_WinResolveImportsOnce, rtHttpWinResolveImports, NULL); 750 if (RT_SUCCESS(rc)) 751 { 752 /* 753 * Try get some proxy info for the URL. We first try getting the IE 754 * config and seeing if we can use WinHttpGetIEProxyConfigForCurrentUser 755 * in some way, if we can we prepare ProxyOptions with a non-zero dwFlags. 756 */ 757 WINHTTP_PROXY_INFO ProxyInfo; 758 PRTUTF16 pwszProxy = NULL; 759 PRTUTF16 pwszNoProxy = NULL; 760 WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions; 761 RT_ZERO(AutoProxyOptions); 762 RT_ZERO(ProxyInfo); 763 764 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG IeProxyConfig; 765 if (g_pfnWinHttpGetIEProxyConfigForCurrentUser(&IeProxyConfig)) 766 { 767 AutoProxyOptions.fAutoLogonIfChallenged = FALSE; 768 AutoProxyOptions.lpszAutoConfigUrl = IeProxyConfig.lpszAutoConfigUrl; 769 if (IeProxyConfig.fAutoDetect) 770 { 771 AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_RUN_INPROCESS; 772 AutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; 773 } 774 else if (AutoProxyOptions.lpszAutoConfigUrl) 775 AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; 776 else if (ProxyInfo.lpszProxy) 777 ProxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; 778 ProxyInfo.lpszProxy = IeProxyConfig.lpszProxy; 779 ProxyInfo.lpszProxyBypass = IeProxyConfig.lpszProxyBypass; 780 } 781 else 782 { 783 AssertMsgFailed(("WinHttpGetIEProxyConfigForCurrentUser -> %u\n", GetLastError())); 784 if (!g_pfnWinHttpGetDefaultProxyConfiguration(&ProxyInfo)) 785 { 786 AssertMsgFailed(("WinHttpGetDefaultProxyConfiguration -> %u\n", GetLastError())); 787 RT_ZERO(ProxyInfo); 788 } 789 } 790 791 /* 792 * Should we try WinHttGetProxyForUrl? 793 */ 794 if (AutoProxyOptions.dwFlags != 0) 795 { 796 HINTERNET hSession = g_pfnWinHttpOpen(NULL /*pwszUserAgent*/, WINHTTP_ACCESS_TYPE_NO_PROXY, 797 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0 /*dwFlags*/ ); 798 if (hSession != NULL) 799 { 800 PRTUTF16 pwszUrl; 801 rc = RTStrToUtf16(pszUrl, &pwszUrl); 802 if (RT_SUCCESS(rc)) 803 { 804 /* 805 * Try autodetect first, then fall back on the config URL if there is one. 806 * 807 * Also, we first try without auto authentication, then with. This will according 808 * to http://msdn.microsoft.com/en-us/library/aa383153%28v=VS.85%29.aspx help with 809 * caching the result when it's processed out-of-process (seems default here on W10). 810 */ 811 WINHTTP_PROXY_INFO TmpProxyInfo; 812 BOOL fRc = g_pfnWinHttpGetProxyForUrl(hSession, pwszUrl, &AutoProxyOptions, &TmpProxyInfo); 813 if ( !fRc 814 && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) 815 { 816 AutoProxyOptions.fAutoLogonIfChallenged = TRUE; 817 fRc = g_pfnWinHttpGetProxyForUrl(hSession, pwszUrl, &AutoProxyOptions, &TmpProxyInfo); 818 } 819 820 if ( !fRc 821 && AutoProxyOptions.dwFlags != WINHTTP_AUTOPROXY_CONFIG_URL 822 && AutoProxyOptions.lpszAutoConfigUrl) 823 { 824 AutoProxyOptions.fAutoLogonIfChallenged = FALSE; 825 AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; 826 AutoProxyOptions.dwAutoDetectFlags = 0; 827 fRc = g_pfnWinHttpGetProxyForUrl(hSession, pwszUrl, &AutoProxyOptions, &TmpProxyInfo); 828 if ( !fRc 829 && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) 830 { 831 AutoProxyOptions.fAutoLogonIfChallenged = TRUE; 832 fRc = g_pfnWinHttpGetProxyForUrl(hSession, pwszUrl, &AutoProxyOptions, &TmpProxyInfo); 833 } 834 } 835 836 if (fRc) 837 { 838 if (ProxyInfo.lpszProxy) 839 GlobalFree(ProxyInfo.lpszProxy); 840 if (ProxyInfo.lpszProxyBypass) 841 GlobalFree(ProxyInfo.lpszProxyBypass); 842 ProxyInfo = TmpProxyInfo; 843 } 844 /* 845 * If the autodetection failed, assume no proxy. 846 */ 847 else 848 { 849 DWORD dwErr = GetLastError(); 850 if (dwErr == ERROR_WINHTTP_AUTODETECTION_FAILED) 851 rcRet = rtHttpUpdateAutomaticProxyDisable(pThis); 852 else 853 AssertMsgFailed(("g_pfnWinHttpGetProxyForUrl -> %u\n", dwErr)); 854 } 855 RTUtf16Free(pwszUrl); 856 } 857 else 858 { 859 AssertMsgFailed(("RTStrToUtf16(%s,) -> %Rrc\n", pszUrl, rc)); 860 rcRet = rc; 861 } 862 g_pfnWinHttpCloseHandle(hSession); 863 } 864 else 865 AssertMsgFailed(("g_pfnWinHttpOpen -> %u\n", GetLastError())); 866 } 867 868 /* 869 * Try use the proxy info we've found. 870 */ 871 switch (ProxyInfo.dwAccessType) 872 { 873 case WINHTTP_ACCESS_TYPE_NO_PROXY: 874 rcRet = rtHttpUpdateAutomaticProxyDisable(pThis); 875 break; 876 877 case WINHTTP_ACCESS_TYPE_NAMED_PROXY: 878 /** @todo Continue here: parse the proxy thingy. */ 879 //AssertMsgFailed(("lpszProxy='%ls'\n", ProxyInfo.lpszProxy)); 880 break; 881 882 case 0: 883 break; 884 885 default: 886 AssertMsgFailed(("%#x\n", ProxyInfo.dwAccessType)); 887 } 888 889 /* 890 * Cleanup. 891 */ 892 if (ProxyInfo.lpszProxy) 893 GlobalFree(ProxyInfo.lpszProxy); 894 if (ProxyInfo.lpszProxyBypass) 895 GlobalFree(ProxyInfo.lpszProxyBypass); 896 if (AutoProxyOptions.lpszAutoConfigUrl) 897 GlobalFree((PRTUTF16)AutoProxyOptions.lpszAutoConfigUrl); 898 } 899 900 return rcRet; 901 } 902 903 #endif /* RT_OS_WINDOWS */ 904 672 905 673 906 static int rtHttpConfigureProxyForUrl(PRTHTTPINTERNAL pThis, const char *pszUrl) … … 675 908 if (pThis->fUseSystemProxySettings) 676 909 { 910 #ifdef RT_OS_WINDOWS 911 int rc = rtHttpConfigureProxyForUrlWindows(pThis, pszUrl); 912 if (rc == VINF_SUCCESS || RT_FAILURE(rc)) 913 return rc; 914 Assert(rc == VINF_NOT_SUPPORTED); 915 #endif 677 916 /** @todo system specific class here, fall back on env vars if necessary. */ 678 917 return rtHttpConfigureProxyForUrlFromEnv(pThis, pszUrl);
Note:
See TracChangeset
for help on using the changeset viewer.