diff --git a/build/cmake/setup.h.in b/build/cmake/setup.h.in index db6e294e51..910ab84305 100644 --- a/build/cmake/setup.h.in +++ b/build/cmake/setup.h.in @@ -691,11 +691,7 @@ #cmakedefine01 wxUSE_GRAPHICS_DIRECT2D #endif -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - #cmakedefine01 wxUSE_WEBREQUEST_WINHTTP -#else - #cmakedefine01 wxUSE_WEBREQUEST_WINHTTP -#endif +#cmakedefine01 wxUSE_WEBREQUEST_WINHTTP #cmakedefine01 wxUSE_OLE diff --git a/include/wx/gtk/setup.h b/include/wx/gtk/setup.h index 77b1827e0f..6695285e4a 100644 --- a/include/wx/gtk/setup.h +++ b/include/wx/gtk/setup.h @@ -1650,11 +1650,7 @@ // // Recommended setting: 1, can be set to 0 if wxUSE_WEBREQUEST_CURL==1, // otherwise wxWebRequest won't be available at all. -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - #define wxUSE_WEBREQUEST_WINHTTP 1 -#else - #define wxUSE_WEBREQUEST_WINHTTP 0 -#endif +#define wxUSE_WEBREQUEST_WINHTTP 1 // ---------------------------------------------------------------------------- // Windows-only settings diff --git a/include/wx/msw/chkconf.h b/include/wx/msw/chkconf.h index 87ac46f30d..f3e847deb8 100644 --- a/include/wx/msw/chkconf.h +++ b/include/wx/msw/chkconf.h @@ -235,6 +235,11 @@ # define wxUSE_ACTIVITYINDICATOR 0 #endif /* !wxUSE_ACTIVITYINDICATOR && !_MSC_VER */ +/* MinGW-w64 (32 and 64 bit) has winhttp.h available, legacy MinGW does not. */ +#if (!defined(_MSC_VER) && !defined(__MINGW64_VERSION_MAJOR)) || !wxUSE_DYNLIB_CLASS + #undef wxUSE_WEBREQUEST_WINHTTP + #define wxUSE_WEBREQUEST_WINHTTP 0 +#endif /* Similarly, turn off wxUSE_WEBREQUEST if we can't enable it because we don't have any of its backends to allow the library to compile with the default diff --git a/include/wx/msw/private/webrequest_winhttp.h b/include/wx/msw/private/webrequest_winhttp.h index dd1f9d5e70..1e961fb811 100644 --- a/include/wx/msw/private/webrequest_winhttp.h +++ b/include/wx/msw/private/webrequest_winhttp.h @@ -136,6 +136,8 @@ public: ~wxWebSessionWinHTTP(); + static bool Initialize(); + wxWebRequestImplPtr CreateRequest(wxWebSession& session, wxEvtHandler* handler, @@ -163,7 +165,14 @@ class wxWebSessionFactoryWinHTTP : public wxWebSessionFactory { public: wxWebSessionImpl* Create() wxOVERRIDE - { return new wxWebSessionWinHTTP(); } + { + return new wxWebSessionWinHTTP(); + } + + bool Initialize() wxOVERRIDE + { + return wxWebSessionWinHTTP::Initialize(); + } }; #endif // _WX_MSW_WEBREQUEST_WINHTTP_H diff --git a/include/wx/msw/setup.h b/include/wx/msw/setup.h index 262f732c94..7b4494ce10 100644 --- a/include/wx/msw/setup.h +++ b/include/wx/msw/setup.h @@ -1650,11 +1650,7 @@ // // Recommended setting: 1, can be set to 0 if wxUSE_WEBREQUEST_CURL==1, // otherwise wxWebRequest won't be available at all. -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - #define wxUSE_WEBREQUEST_WINHTTP 1 -#else - #define wxUSE_WEBREQUEST_WINHTTP 0 -#endif +#define wxUSE_WEBREQUEST_WINHTTP 1 // ---------------------------------------------------------------------------- // Windows-only settings diff --git a/include/wx/msw/setup_inc.h b/include/wx/msw/setup_inc.h index 4957536e92..480b7a9344 100644 --- a/include/wx/msw/setup_inc.h +++ b/include/wx/msw/setup_inc.h @@ -44,11 +44,7 @@ // // Recommended setting: 1, can be set to 0 if wxUSE_WEBREQUEST_CURL==1, // otherwise wxWebRequest won't be available at all. -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - #define wxUSE_WEBREQUEST_WINHTTP 1 -#else - #define wxUSE_WEBREQUEST_WINHTTP 0 -#endif +#define wxUSE_WEBREQUEST_WINHTTP 1 // ---------------------------------------------------------------------------- // Windows-only settings diff --git a/include/wx/private/webrequest.h b/include/wx/private/webrequest.h index 497bbfc170..1b18d583c6 100644 --- a/include/wx/private/webrequest.h +++ b/include/wx/private/webrequest.h @@ -212,6 +212,8 @@ class wxWebSessionFactory public: virtual wxWebSessionImpl* Create() = 0; + virtual bool Initialize() { return true; } + virtual ~wxWebSessionFactory() { } }; diff --git a/samples/webrequest/webrequest.cpp b/samples/webrequest/webrequest.cpp index 3a16eda371..95ce7a4261 100644 --- a/samples/webrequest/webrequest.cpp +++ b/samples/webrequest/webrequest.cpp @@ -10,10 +10,6 @@ // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" -#ifdef __BORLANDC__ - #pragma hdrstop -#endif - #ifndef WX_PRECOMP #include "wx/wx.h" #endif @@ -29,6 +25,10 @@ #include "../sample.xpm" #endif +#if !wxUSE_WEBREQUEST +#error "wxUSE_WEBREQUEST must be 1 for this sample." +#endif + class WebRequestFrame : public wxFrame { public: diff --git a/setup.h.in b/setup.h.in index 711f4dc682..895b8f2b57 100644 --- a/setup.h.in +++ b/setup.h.in @@ -691,11 +691,7 @@ #define wxUSE_GRAPHICS_DIRECT2D 0 #endif -#if defined(_MSC_VER) || defined(__MINGW64_VERSION_MAJOR) - #define wxUSE_WEBREQUEST_WINHTTP 0 -#else - #define wxUSE_WEBREQUEST_WINHTTP 0 -#endif +#define wxUSE_WEBREQUEST_WINHTTP 0 #define wxUSE_OLE 0 diff --git a/src/common/webrequest.cpp b/src/common/webrequest.cpp index 20bf309dc2..5baca038be 100644 --- a/src/common/webrequest.cpp +++ b/src/common/webrequest.cpp @@ -942,6 +942,13 @@ void wxWebSession::RegisterFactory(const wxString& backend, wxWebSessionFactory* factory) { + if ( !factory->Initialize() ) + { + delete factory; + factory = NULL; + return; + } + // Note that we don't have to check here that there is no registered // backend with the same name yet because we're only called from // InitFactoryMap() below. If this function becomes public, we'd need to diff --git a/src/common/webrequest_curl.cpp b/src/common/webrequest_curl.cpp index 17dc62b13d..91a8aec4ac 100644 --- a/src/common/webrequest_curl.cpp +++ b/src/common/webrequest_curl.cpp @@ -12,7 +12,7 @@ #include "wx/webrequest.h" -#if wxUSE_WEBREQUEST_CURL +#if wxUSE_WEBREQUEST && wxUSE_WEBREQUEST_CURL #include "wx/private/webrequest_curl.h" @@ -461,7 +461,7 @@ wxDEFINE_EVENT(wxEVT_SOCKET_POLLER_RESULT, wxThreadEvent); class SocketPollerImpl { public: - virtual ~SocketPollerImpl(){}; + virtual ~SocketPollerImpl(){} virtual bool StartPolling(wxSOCKET_T, int) = 0; virtual void StopPolling(wxSOCKET_T) = 0; virtual void ResumePolling(wxSOCKET_T) = 0; diff --git a/src/msw/webrequest_winhttp.cpp b/src/msw/webrequest_winhttp.cpp index 11f8197118..d31c12ef05 100644 --- a/src/msw/webrequest_winhttp.cpp +++ b/src/msw/webrequest_winhttp.cpp @@ -12,9 +12,10 @@ #include "wx/webrequest.h" -#if wxUSE_WEBREQUEST_WINHTTP +#if wxUSE_WEBREQUEST && wxUSE_WEBREQUEST_WINHTTP #include "wx/mstream.h" +#include "wx/dynlib.h" #include "wx/msw/private.h" #include "wx/msw/private/webrequest_winhttp.h" @@ -24,11 +25,94 @@ #include "wx/translation.h" #endif -// For MSVC we can link in the required library explicitly, for the other -// compilers (e.g. MinGW) this needs to be done at makefiles level. -#ifdef __VISUALC__ -#pragma comment(lib, "winhttp") -#endif +// Helper class used to dynamically load the required symbols from winhttp.dll +class wxWinHTTP +{ +public: + static bool LoadLibrary() + { + bool result = m_winhttp.Load("winhttp.dll", wxDL_VERBATIM | wxDL_QUIET); + if ( !result ) + return result; + + #define wxLOAD_FUNC(name) \ + wxDL_INIT_FUNC(, name, m_winhttp); \ + result &= (name != NULL); + + wxLOAD_FUNC(WinHttpQueryOption) + wxLOAD_FUNC(WinHttpQueryHeaders) + wxLOAD_FUNC(WinHttpSetOption) + wxLOAD_FUNC(WinHttpWriteData) + wxLOAD_FUNC(WinHttpCloseHandle) + wxLOAD_FUNC(WinHttpReceiveResponse) + wxLOAD_FUNC(WinHttpCrackUrl) + wxLOAD_FUNC(WinHttpConnect) + wxLOAD_FUNC(WinHttpOpenRequest) + wxLOAD_FUNC(WinHttpSetStatusCallback) + wxLOAD_FUNC(WinHttpSendRequest) + wxLOAD_FUNC(WinHttpReadData) + wxLOAD_FUNC(WinHttpQueryAuthSchemes) + wxLOAD_FUNC(WinHttpSetCredentials) + wxLOAD_FUNC(WinHttpOpen) + + if ( !result ) + m_winhttp.Unload(); + + return result; + } + + typedef BOOL(WINAPI* WinHttpQueryOption_t)(HINTERNET, DWORD, LPVOID, LPDWORD); + static WinHttpQueryOption_t WinHttpQueryOption; + typedef BOOL(WINAPI* WinHttpQueryHeaders_t)(HINTERNET, DWORD, LPCWSTR, LPVOID, LPDWORD, LPDWORD); + static WinHttpQueryHeaders_t WinHttpQueryHeaders; + typedef BOOL(WINAPI* WinHttpSetOption_t)(HINTERNET, DWORD, LPVOID, DWORD); + static WinHttpSetOption_t WinHttpSetOption; + typedef BOOL(WINAPI* WinHttpWriteData_t)(HINTERNET, LPCVOID, DWORD, LPDWORD); + static WinHttpWriteData_t WinHttpWriteData; + typedef BOOL(WINAPI* WinHttpCloseHandle_t)(HINTERNET); + static WinHttpCloseHandle_t WinHttpCloseHandle; + typedef BOOL(WINAPI* WinHttpReceiveResponse_t)(HINTERNET, LPVOID); + static WinHttpReceiveResponse_t WinHttpReceiveResponse; + typedef BOOL(WINAPI* WinHttpCrackUrl_t)(LPCWSTR, DWORD, DWORD, LPURL_COMPONENTS); + static WinHttpCrackUrl_t WinHttpCrackUrl; + typedef HINTERNET(WINAPI* WinHttpConnect_t)(HINTERNET, LPCWSTR, INTERNET_PORT, DWORD); + static WinHttpConnect_t WinHttpConnect; + typedef HINTERNET(WINAPI* WinHttpOpenRequest_t)(HINTERNET, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR*, DWORD); + static WinHttpOpenRequest_t WinHttpOpenRequest; + typedef WINHTTP_STATUS_CALLBACK(WINAPI* WinHttpSetStatusCallback_t)(HINTERNET, WINHTTP_STATUS_CALLBACK, DWORD, DWORD_PTR); + static WinHttpSetStatusCallback_t WinHttpSetStatusCallback; + typedef BOOL(WINAPI* WinHttpSendRequest_t)(HINTERNET, LPCWSTR, DWORD, LPVOID, DWORD, DWORD, DWORD_PTR); + static WinHttpSendRequest_t WinHttpSendRequest; + typedef BOOL(WINAPI* WinHttpReadData_t)(HINTERNET, LPVOID, DWORD, LPDWORD); + static WinHttpReadData_t WinHttpReadData; + typedef BOOL(WINAPI* WinHttpQueryAuthSchemes_t)(HINTERNET, LPDWORD, LPDWORD, LPDWORD); + static WinHttpQueryAuthSchemes_t WinHttpQueryAuthSchemes; + typedef BOOL(WINAPI* WinHttpSetCredentials_t)(HINTERNET, DWORD, DWORD, LPCWSTR, LPCWSTR, LPVOID); + static WinHttpSetCredentials_t WinHttpSetCredentials; + typedef HINTERNET(WINAPI* WinHttpOpen_t)(LPCWSTR, DWORD, LPCWSTR, LPCWSTR, DWORD); + static WinHttpOpen_t WinHttpOpen; + +private: + static wxDynamicLibrary m_winhttp; +}; + +wxDynamicLibrary wxWinHTTP::m_winhttp; +wxWinHTTP::WinHttpQueryOption_t wxWinHTTP::WinHttpQueryOption; +wxWinHTTP::WinHttpQueryHeaders_t wxWinHTTP::WinHttpQueryHeaders; +wxWinHTTP::WinHttpSetOption_t wxWinHTTP::WinHttpSetOption; +wxWinHTTP::WinHttpWriteData_t wxWinHTTP::WinHttpWriteData; +wxWinHTTP::WinHttpCloseHandle_t wxWinHTTP::WinHttpCloseHandle; +wxWinHTTP::WinHttpReceiveResponse_t wxWinHTTP::WinHttpReceiveResponse; +wxWinHTTP::WinHttpCrackUrl_t wxWinHTTP::WinHttpCrackUrl; +wxWinHTTP::WinHttpConnect_t wxWinHTTP::WinHttpConnect; +wxWinHTTP::WinHttpOpenRequest_t wxWinHTTP::WinHttpOpenRequest; +wxWinHTTP::WinHttpSetStatusCallback_t wxWinHTTP::WinHttpSetStatusCallback; +wxWinHTTP::WinHttpSendRequest_t wxWinHTTP::WinHttpSendRequest; +wxWinHTTP::WinHttpReadData_t wxWinHTTP::WinHttpReadData; +wxWinHTTP::WinHttpQueryAuthSchemes_t wxWinHTTP::WinHttpQueryAuthSchemes; +wxWinHTTP::WinHttpSetCredentials_t wxWinHTTP::WinHttpSetCredentials; +wxWinHTTP::WinHttpOpen_t wxWinHTTP::WinHttpOpen; + // Define constants potentially missing in old SDKs #ifndef WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY @@ -64,12 +148,12 @@ static wxString wxWinHTTPQueryHeaderString(HINTERNET hRequest, DWORD dwInfoLevel { wxString result; DWORD bufferLen = 0; - ::WinHttpQueryHeaders(hRequest, dwInfoLevel, pwszName, NULL, &bufferLen, + wxWinHTTP::WinHttpQueryHeaders(hRequest, dwInfoLevel, pwszName, NULL, &bufferLen, WINHTTP_NO_HEADER_INDEX); if ( ::GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { wxWCharBuffer resBuf(bufferLen); - if ( ::WinHttpQueryHeaders(hRequest, dwInfoLevel, pwszName, + if ( wxWinHTTP::WinHttpQueryHeaders(hRequest, dwInfoLevel, pwszName, resBuf.data(), &bufferLen, WINHTTP_NO_HEADER_INDEX) ) { @@ -84,11 +168,11 @@ static wxString wxWinHTTPQueryOptionString(HINTERNET hInternet, DWORD dwOption) { wxString result; DWORD bufferLen = 0; - ::WinHttpQueryOption(hInternet, dwOption, NULL, &bufferLen); + wxWinHTTP::WinHttpQueryOption(hInternet, dwOption, NULL, &bufferLen); if ( ::GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { wxWCharBuffer resBuf(bufferLen); - if ( ::WinHttpQueryOption(hInternet, dwOption, resBuf.data(), &bufferLen) ) + if ( wxWinHTTP::WinHttpQueryOption(hInternet, dwOption, resBuf.data(), &bufferLen) ) result.assign(resBuf); } @@ -98,13 +182,13 @@ static wxString wxWinHTTPQueryOptionString(HINTERNET hInternet, DWORD dwOption) static inline void wxWinHTTPSetOption(HINTERNET hInternet, DWORD dwOption, DWORD dwValue) { - ::WinHttpSetOption(hInternet, dwOption, &dwValue, sizeof(dwValue)); + wxWinHTTP::WinHttpSetOption(hInternet, dwOption, &dwValue, sizeof(dwValue)); } static void wxWinHTTPCloseHandle(HINTERNET hInternet) { - if ( !::WinHttpCloseHandle(hInternet) ) + if ( !wxWinHTTP::WinHttpCloseHandle(hInternet) ) { wxLogLastError("WinHttpCloseHandle"); } @@ -225,7 +309,7 @@ void wxWebRequestWinHTTP::WriteData() void* buffer = m_dataWriteBuffer.GetWriteBuf(dataWriteSize); m_dataStream->Read(buffer, dataWriteSize); - if ( !::WinHttpWriteData + if ( !wxWinHTTP::WinHttpWriteData ( m_request, m_dataWriteBuffer.GetData(), @@ -241,7 +325,7 @@ void wxWebRequestWinHTTP::CreateResponse() { wxLogTrace(wxTRACE_WEBREQUEST, "Request %p: creating response", this); - if ( !::WinHttpReceiveResponse(m_request, NULL) ) + if ( !wxWinHTTP::WinHttpReceiveResponse(m_request, NULL) ) { SetFailedWithLastError("Receiving response"); return; @@ -308,14 +392,14 @@ void wxWebRequestWinHTTP::Start() urlComps.dwUrlPathLength = urlComps.dwExtraInfoLength = (DWORD)-1; - if ( !::WinHttpCrackUrl(m_url.wc_str(), m_url.length(), 0, &urlComps) ) + if ( !wxWinHTTP::WinHttpCrackUrl(m_url.wc_str(), m_url.length(), 0, &urlComps) ) { SetFailedWithLastError("Parsing URL"); return; } // Open a connection - m_connect = ::WinHttpConnect + m_connect = wxWinHTTP::WinHttpConnect ( m_sessionImpl.GetHandle(), wxString(urlComps.lpszHostName, urlComps.dwHostNameLength).wc_str(), @@ -334,7 +418,7 @@ void wxWebRequestWinHTTP::Start() // Open a request static const wchar_t* acceptedTypes[] = { L"*/*", NULL }; - m_request = ::WinHttpOpenRequest + m_request = wxWinHTTP::WinHttpOpenRequest ( m_connect, method.wc_str(), objectName.wc_str(), @@ -352,7 +436,7 @@ void wxWebRequestWinHTTP::Start() } // Register callback - if ( ::WinHttpSetStatusCallback + if ( wxWinHTTP::WinHttpSetStatusCallback ( m_request, wxRequestStatusCallback, @@ -397,7 +481,7 @@ void wxWebRequestWinHTTP::SendRequest() SetState(wxWebRequest::State_Active); // Send request - if ( !::WinHttpSendRequest + if ( !wxWinHTTP::WinHttpSendRequest ( m_request, allHeaders.wc_str(), allHeaders.length(), @@ -452,7 +536,7 @@ int wxWebResponseWinHTTP::GetStatus() const { DWORD status = 0; DWORD statusSize = sizeof(status); - if ( !::WinHttpQueryHeaders + if ( !wxWinHTTP::WinHttpQueryHeaders ( m_requestHandle, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, @@ -477,7 +561,7 @@ bool wxWebResponseWinHTTP::ReadData() { wxLogTrace(wxTRACE_WEBREQUEST, "Request %p: reading data", &m_request); - return ::WinHttpReadData + return wxWinHTTP::WinHttpReadData ( m_requestHandle, GetDataBuffer(m_readSize), @@ -510,7 +594,7 @@ bool wxWebAuthChallengeWinHTTP::Init() DWORD supportedSchemes; DWORD firstScheme; - if ( !::WinHttpQueryAuthSchemes + if ( !wxWinHTTP::WinHttpQueryAuthSchemes ( m_request.GetHandle(), &supportedSchemes, @@ -541,7 +625,7 @@ bool wxWebAuthChallengeWinHTTP::Init() void wxWebAuthChallengeWinHTTP::SetCredentials(const wxWebCredentials& cred) { - if ( !::WinHttpSetCredentials + if ( !wxWinHTTP::WinHttpSetCredentials ( m_request.GetHandle(), m_target, @@ -574,6 +658,11 @@ wxWebSessionWinHTTP::~wxWebSessionWinHTTP() wxWinHTTPCloseHandle(m_handle); } +bool wxWebSessionWinHTTP::Initialize() +{ + return wxWinHTTP::LoadLibrary(); +} + bool wxWebSessionWinHTTP::Open() { DWORD accessType; @@ -582,7 +671,7 @@ bool wxWebSessionWinHTTP::Open() else accessType = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; - m_handle = ::WinHttpOpen + m_handle = wxWinHTTP::WinHttpOpen ( GetHeaders().find("User-Agent")->second.wc_str(), accessType, diff --git a/src/osx/webrequest_urlsession.mm b/src/osx/webrequest_urlsession.mm index f522d41391..cd101335c2 100644 --- a/src/osx/webrequest_urlsession.mm +++ b/src/osx/webrequest_urlsession.mm @@ -12,7 +12,7 @@ #include "wx/webrequest.h" -#if wxUSE_WEBREQUEST_URLSESSION +#if wxUSE_WEBREQUEST && wxUSE_WEBREQUEST_URLSESSION #import