VirtualBox

Changeset 57749 in vbox for trunk


Ignore:
Timestamp:
Sep 14, 2015 7:33:23 PM (9 years ago)
Author:
vboxsync
Message:

http-curl.cpp: Halfways there on windows, just need to make use of the settings now.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/generic/http-curl.cpp

    r57737 r57749  
    11/* $Id$ */
    22/** @file
    3  * IPRT - HTTP communication API.
     3 * IPRT - HTTP client API, cURL based.
    44 */
    55
     
    3939#include <iprt/err.h>
    4040#include <iprt/file.h>
     41#ifdef RT_OS_WINDOWS
     42# include <iprt/ldr.h>
     43#endif
    4144#include <iprt/mem.h>
     45#include <iprt/once.h>
    4246#include <iprt/path.h>
    4347#include <iprt/stream.h>
     
    4852
    4953#include <curl/curl.h>
     54
     55#ifdef RT_OS_WINDOWS
     56# include <Winhttp.h>
     57#endif
    5058
    5159
     
    126134
    127135
     136#ifdef RT_OS_WINDOWS
     137/** @name Windows: Types for dynamically resolved APIs
     138 * @{ */
     139typedef HINTERNET (WINAPI * PFNWINHTTPOPEN)(LPCWSTR, DWORD, LPCWSTR, LPCWSTR, DWORD);
     140typedef BOOL      (WINAPI * PFNWINHTTPCLOSEHANDLE)(HINTERNET);
     141typedef BOOL      (WINAPI * PFNWINHTTPGETPROXYFORURL)(HINTERNET, LPCWSTR, WINHTTP_AUTOPROXY_OPTIONS *, WINHTTP_PROXY_INFO *);
     142typedef BOOL      (WINAPI * PFNWINHTTPGETDEFAULTPROXYCONFIGURATION)(WINHTTP_PROXY_INFO *);
     143typedef BOOL      (WINAPI * PFNWINHTTPGETIEPROXYCONFIGFORCURRENTUSER)(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *);
     144/** @} */
     145#endif
     146
     147
    128148/*********************************************************************************************************************************
    129149*   Defined Constants And Macros                                                                                                 *
     
    161181        AssertReturnVoid((hHttp)->u32Magic == RTHTTP_MAGIC); \
    162182    } while (0)
     183
     184
     185/*********************************************************************************************************************************
     186*   Global Variables                                                                                                             *
     187*********************************************************************************************************************************/
     188#ifdef RT_OS_WINDOWS
     189/** @name Windows: Dynamically resolved APIs
     190 * @{ */
     191static RTONCE                                   g_WinResolveImportsOnce = RTONCE_INITIALIZER;
     192static RTLDRMOD                                 g_hWinHttpMod = NIL_RTLDRMOD;
     193static PFNWINHTTPOPEN                           g_pfnWinHttpOpen = NULL;
     194static PFNWINHTTPCLOSEHANDLE                    g_pfnWinHttpCloseHandle = NULL;
     195static PFNWINHTTPGETPROXYFORURL                 g_pfnWinHttpGetProxyForUrl = NULL;
     196static PFNWINHTTPGETDEFAULTPROXYCONFIGURATION   g_pfnWinHttpGetDefaultProxyConfiguration = NULL;
     197static PFNWINHTTPGETIEPROXYCONFIGFORCURRENTUSER g_pfnWinHttpGetIEProxyConfigForCurrentUser = NULL;
     198/** @} */
     199#endif
    163200
    164201
     
    670707}
    671708
     709#ifdef RT_OS_WINDOWS
     710
     711/**
     712 * @callback_method_impl{FNRTONCE, Loads WinHttp.dll and resolves APIs}
     713 */
     714static 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 */
     745static 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
    672905
    673906static int rtHttpConfigureProxyForUrl(PRTHTTPINTERNAL pThis, const char *pszUrl)
     
    675908    if (pThis->fUseSystemProxySettings)
    676909    {
     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
    677916/** @todo system specific class here, fall back on env vars if necessary. */
    678917        return rtHttpConfigureProxyForUrlFromEnv(pThis, pszUrl);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette