From 6023925ef665ccdc04e452d89b09bf48d75488b7 Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 19 Jul 2020 14:25:37 +0200 Subject: [PATCH 1/3] Allow using XMLHTTP ActiveX object with custom scheme handlers Fix the problem of the access-denied error when using a 'new window.ActiveXObject("Microsoft.XMLHTTP")' to access URIs from custom WebView scheme handler of the Internet Explorer WebView. The solution here is to implement PARSE_SECURITY_URL and PARSE_SECURITY_DOMAIN in ParseUrl of the IInternetProtocolInfo interface of the Internet Explorer Control. The direct implementation of VirtualProtocol::QueryInterface() instead of using IMPLEMENT_IUNKNOWN_METHODS works, but is not nice. The better approach would be probably enhancing ADD_RAW_IID to support multiple inheritance. Closes #17893. --- include/wx/msw/private/webview_ie.h | 23 +++- include/wx/msw/private/webview_missing.h | 32 ++++++ src/msw/webview_ie.cpp | 135 ++++++++++++++++++++++- 3 files changed, 188 insertions(+), 2 deletions(-) diff --git a/include/wx/msw/private/webview_ie.h b/include/wx/msw/private/webview_ie.h index d350340f30..4d94911aaa 100644 --- a/include/wx/msw/private/webview_ie.h +++ b/include/wx/msw/private/webview_ie.h @@ -73,7 +73,7 @@ public: wxDECLARE_NO_COPY_CLASS(wxWebViewIEImpl); }; -class VirtualProtocol : public wxIInternetProtocol +class VirtualProtocol : public wxIInternetProtocol, public wxIInternetProtocolInfo { protected: wxIInternetProtocolSink* m_protocolSink; @@ -114,6 +114,27 @@ public: ULARGE_INTEGER* WXUNUSED(plibNewPosition)) wxOVERRIDE { return E_FAIL; } HRESULT STDMETHODCALLTYPE UnlockRequest() wxOVERRIDE { return S_OK; } + + //IInternetProtocolInfo + HRESULT STDMETHODCALLTYPE CombineUrl( + LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, + DWORD dwCombineFlags, LPWSTR pwzResult, + DWORD cchResult, DWORD *pcchResult, + DWORD dwReserved) wxOVERRIDE; + HRESULT STDMETHODCALLTYPE ParseUrl( + LPCWSTR pwzUrl, PARSEACTION ParseAction, + DWORD dwParseFlags, LPWSTR pwzResult, + DWORD cchResult, DWORD *pcchResult, + DWORD dwReserved) wxOVERRIDE; + HRESULT STDMETHODCALLTYPE CompareUrl( + LPCWSTR pwzUrl1, + LPCWSTR pwzUrl2, + DWORD dwCompareFlags) wxOVERRIDE; + HRESULT STDMETHODCALLTYPE QueryInfo( + LPCWSTR pwzUrl, QUERYOPTION OueryOption, + DWORD dwQueryFlags, LPVOID pBuffer, + DWORD cbBuffer, DWORD *pcbBuf, + DWORD dwReserved) wxOVERRIDE; }; class ClassFactory : public IClassFactory diff --git a/include/wx/msw/private/webview_missing.h b/include/wx/msw/private/webview_missing.h index 2efadd9f0c..12602717bd 100644 --- a/include/wx/msw/private/webview_missing.h +++ b/include/wx/msw/private/webview_missing.h @@ -136,6 +136,38 @@ public: DWORD dwReserved) = 0; }; +class wxIInternetProtocolInfo : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE ParseUrl(LPCWSTR pwzUrl, + PARSEACTION ParseAction, + DWORD dwParseFlags, + LPWSTR pwzResult, + DWORD cchResult, + DWORD *pcchResult, + DWORD dwReserved) = 0; + + virtual HRESULT STDMETHODCALLTYPE CombineUrl(LPCWSTR pwzBaseUrl, + LPCWSTR pwzRelativeUrl, + DWORD dwCombineFlags, + LPWSTR pwzResult, + DWORD cchResult, + DWORD *pcchResult, + DWORD dwReserved) = 0; + + virtual HRESULT STDMETHODCALLTYPE CompareUrl(LPCWSTR pwzUrl1, + LPCWSTR pwzUrl2, + DWORD dwCompareFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE QueryInfo(LPCWSTR pwzUrl, + QUERYOPTION OueryOption, + DWORD dwQueryFlags, + LPVOID pBuffer, + DWORD cbBuffer, + DWORD *pcbBuf, + DWORD dwReserved) = 0; +}; + /* end of urlmon.h */ /* mshtmhst.h */ diff --git a/src/msw/webview_ie.cpp b/src/msw/webview_ie.cpp index fe6a83bc73..9942a0420e 100644 --- a/src/msw/webview_ie.cpp +++ b/src/msw/webview_ie.cpp @@ -40,6 +40,7 @@ namespace { DEFINE_GUID(wxIID_IInternetProtocolRoot,0x79eac9e3,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb); DEFINE_GUID(wxIID_IInternetProtocol,0x79eac9e4,0xbaf9,0x11ce,0x8c,0x82,0,0xaa,0,0x4b,0xa9,0xb); +DEFINE_GUID(wxIID_IInternetProtocolInfo,0x79eac9ec,0xbaf9,0x11ce,0x8c, 0x82,0,0xaa,0,0x4b,0xa9,0x0b); DEFINE_GUID(wxIID_IDocHostUIHandler, 0xbd3f23c0, 0xd43e, 0x11cf, 0x89, 0x3b, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x1a); DEFINE_GUID(wxIID_IHTMLElement2,0x3050f434,0x98b5,0x11cf,0xbb,0x82,0,0xaa,0,0xbd,0xce,0x0b); DEFINE_GUID(wxIID_IMarkupServices,0x3050f4a0,0x98b5,0x11cf,0xbb,0x82,0,0xaa,0,0xbd,0xce,0x0b); @@ -1621,7 +1622,61 @@ BEGIN_IID_TABLE(VirtualProtocol) ADD_RAW_IID(wxIID_IInternetProtocol) END_IID_TABLE; -IMPLEMENT_IUNKNOWN_METHODS(VirtualProtocol) +STDMETHODIMP VirtualProtocol::QueryInterface(REFIID riid, void **ppv) +{ + wxLogQueryInterface(wxT("VirtualProtocol"), riid); + + if(riid == IID_IUnknown) + { + wxIInternetProtocolRoot *InternetProtocolRoot = this; + IUnknown *Unknown = InternetProtocolRoot; + *ppv = Unknown; + AddRef(); + return S_OK; + } + if(riid == wxIID_IInternetProtocolRoot) + { + wxIInternetProtocolRoot *InternetProtocolRoot = this; + *ppv = InternetProtocolRoot; + AddRef(); + return S_OK; + } + if(riid == wxIID_IInternetProtocol) + { + wxIInternetProtocol *InternetProtocol = this; + *ppv = InternetProtocol; + AddRef(); + return S_OK; + } + if(riid == wxIID_IInternetProtocolInfo) + { + wxIInternetProtocolInfo *InternetProtocolInfo = this; + *ppv = InternetProtocolInfo; + AddRef(); + return S_OK; + } + + *ppv = NULL; + return (HRESULT) E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) VirtualProtocol::AddRef() +{ + wxLogAddRef(wxT("VirtualProtocol"), m_cRef); + return ++m_cRef; +} + +STDMETHODIMP_(ULONG) VirtualProtocol::Release() +{ + wxLogRelease(wxT("VirtualProtocol"), m_cRef); + if( --m_cRef == wxAutoULong(0)) + { + delete this; + return 0; + } + else + return m_cRef; +} HRESULT STDMETHODCALLTYPE VirtualProtocol::Start(LPCWSTR szUrl, wxIInternetProtocolSink *pOIProtSink, wxIInternetBindInfo *pOIBindInfo, DWORD grfPI, @@ -1689,6 +1744,84 @@ HRESULT STDMETHODCALLTYPE VirtualProtocol::Read(void *pv, ULONG cb, ULONG *pcbRe } } +HRESULT STDMETHODCALLTYPE VirtualProtocol::CombineUrl( + LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, + DWORD dwCombineFlags, LPWSTR pwzResult, + DWORD cchResult, DWORD *pcchResult, + DWORD dwReserved) +{ + wxUnusedVar(pwzBaseUrl); + wxUnusedVar(pwzRelativeUrl); + wxUnusedVar(dwCombineFlags); + wxUnusedVar(pwzResult); + wxUnusedVar(cchResult); + wxUnusedVar(pcchResult); + wxUnusedVar(dwReserved); + + return INET_E_DEFAULT_ACTION; +} + +HRESULT STDMETHODCALLTYPE VirtualProtocol::ParseUrl( + LPCWSTR pwzUrl, PARSEACTION ParseAction, + DWORD dwParseFlags, LPWSTR pwzResult, + DWORD cchResult, DWORD *pcchResult, + DWORD dwReserved) +{ + wxUnusedVar(pwzUrl); + wxUnusedVar(ParseAction); + wxUnusedVar(dwParseFlags); + wxUnusedVar(pwzResult); + wxUnusedVar(cchResult); + wxUnusedVar(pcchResult); + wxUnusedVar(dwReserved); + + switch (ParseAction) + { + case PARSE_SECURITY_URL: + case PARSE_SECURITY_DOMAIN: + { + LPWSTR Result = L"http://localhost"; + size_t Len = wcslen(Result); + if(cchResult <= Len) + return S_FALSE; + wcscpy(pwzResult, Result); + *pcchResult = Len; + return S_OK; + } + } + + return INET_E_DEFAULT_ACTION; +} + +HRESULT STDMETHODCALLTYPE VirtualProtocol::CompareUrl( + LPCWSTR pwzUrl1, + LPCWSTR pwzUrl2, + DWORD dwCompareFlags) +{ + wxUnusedVar(pwzUrl1); + wxUnusedVar(pwzUrl2); + wxUnusedVar(dwCompareFlags); + + return INET_E_DEFAULT_ACTION; +} + +HRESULT STDMETHODCALLTYPE VirtualProtocol::QueryInfo( + LPCWSTR pwzUrl, QUERYOPTION OueryOption, + DWORD dwQueryFlags, LPVOID pBuffer, + DWORD cbBuffer, DWORD *pcbBuf, + DWORD dwReserved) +{ + wxUnusedVar(pwzUrl); + wxUnusedVar(OueryOption); + wxUnusedVar(dwQueryFlags); + wxUnusedVar(pBuffer); + wxUnusedVar(cbBuffer); + wxUnusedVar(pcbBuf); + wxUnusedVar(dwReserved); + + return INET_E_DEFAULT_ACTION; +} + BEGIN_IID_TABLE(ClassFactory) ADD_IID(Unknown) ADD_IID(ClassFactory) From 5c1f7733ab9bccf989aafa13219804367afbc1fa Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 19 Jul 2020 14:19:18 +0200 Subject: [PATCH 2/3] Mark IE-based wxWebView as being DPI aware This makes it work (better) in high DPI. Closes #17894. --- include/wx/msw/private/webview_missing.h | 3 ++- src/msw/webview_ie.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/wx/msw/private/webview_missing.h b/include/wx/msw/private/webview_missing.h index 12602717bd..e3f70c3300 100644 --- a/include/wx/msw/private/webview_missing.h +++ b/include/wx/msw/private/webview_missing.h @@ -198,7 +198,8 @@ typedef enum _tagwxDOCHOSTUIFLAG DOCHOSTUIFLAG_DISABLE_EDIT_NS_FIXUP = 0x400000, DOCHOSTUIFLAG_LOCAL_MACHINE_ACCESS_CHECK = 0x800000, DOCHOSTUIFLAG_DISABLE_UNTRUSTEDPROTOCOL = 0x1000000, - DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION = 0x4000000 + DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION = 0x4000000, + DOCHOSTUIFLAG_DPI_AWARE = 0x40000000 } DOCHOSTUIFLAG; typedef struct _tagwxDOCHOSTUIINFO diff --git a/src/msw/webview_ie.cpp b/src/msw/webview_ie.cpp index 9942a0420e..6b7aba1922 100644 --- a/src/msw/webview_ie.cpp +++ b/src/msw/webview_ie.cpp @@ -1892,7 +1892,8 @@ HRESULT wxSTDCALL DocHostUIHandler::GetHostInfo(DOCHOSTUIINFO *pInfo) // redirected. pInfo->dwFlags |= DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_THEME | - DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION; + DOCHOSTUIFLAG_ENABLE_REDIRECT_NOTIFICATION | + DOCHOSTUIFLAG_DPI_AWARE; return S_OK; } From cd2cd6a61778eda7dcb1d94184753481a5dfd78f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 21 Jul 2020 17:46:37 +0200 Subject: [PATCH 3/3] Avoid using IE-related symbols not present in old MinGW headers Define INET_E_DEFAULT_ACTION ourselves and provide stand-ins for the enums not present in MinGW SDK. See #17893. --- include/wx/msw/private/webview_ie.h | 4 ++-- include/wx/msw/private/webview_missing.h | 23 +++++++++++++++++++++-- src/msw/webview_ie.cpp | 8 ++++---- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/include/wx/msw/private/webview_ie.h b/include/wx/msw/private/webview_ie.h index 4d94911aaa..091167f17b 100644 --- a/include/wx/msw/private/webview_ie.h +++ b/include/wx/msw/private/webview_ie.h @@ -122,7 +122,7 @@ public: DWORD cchResult, DWORD *pcchResult, DWORD dwReserved) wxOVERRIDE; HRESULT STDMETHODCALLTYPE ParseUrl( - LPCWSTR pwzUrl, PARSEACTION ParseAction, + LPCWSTR pwzUrl, wxPARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved) wxOVERRIDE; @@ -131,7 +131,7 @@ public: LPCWSTR pwzUrl2, DWORD dwCompareFlags) wxOVERRIDE; HRESULT STDMETHODCALLTYPE QueryInfo( - LPCWSTR pwzUrl, QUERYOPTION OueryOption, + LPCWSTR pwzUrl, wxQUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved) wxOVERRIDE; diff --git a/include/wx/msw/private/webview_missing.h b/include/wx/msw/private/webview_missing.h index e3f70c3300..6d3196c10f 100644 --- a/include/wx/msw/private/webview_missing.h +++ b/include/wx/msw/private/webview_missing.h @@ -27,6 +27,10 @@ struct IHTMLDocument2; #define REFRESH_COMPLETELY 3 #endif +#ifndef INET_E_DEFAULT_ACTION +#define INET_E_DEFAULT_ACTION ((HRESULT)0x800C0011L) +#endif + typedef enum __wxMIDL_IBindStatusCallback_0006 { wxBSCF_FIRSTDATANOTIFICATION = 0x1, @@ -136,11 +140,26 @@ public: DWORD dwReserved) = 0; }; +// This interface uses a couple of enums which are not defined in old MinGW +// SDK headers, but we don't have any reliable way to test if they're actually +// defined, so define our own enums, containing just the values we need: this +// compiles everywhere and is ABI-compatible with the real enums. +enum wxPARSEACTION +{ + wxPARSE_SECURITY_URL = 3, + wxPARSE_SECURITY_DOMAIN = 17 +}; + +enum wxQUERYOPTION +{ + // We don't actually need any values in this one. +}; + class wxIInternetProtocolInfo : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE ParseUrl(LPCWSTR pwzUrl, - PARSEACTION ParseAction, + wxPARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, @@ -160,7 +179,7 @@ public: DWORD dwCompareFlags) = 0; virtual HRESULT STDMETHODCALLTYPE QueryInfo(LPCWSTR pwzUrl, - QUERYOPTION OueryOption, + wxQUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, diff --git a/src/msw/webview_ie.cpp b/src/msw/webview_ie.cpp index 6b7aba1922..839acc92f3 100644 --- a/src/msw/webview_ie.cpp +++ b/src/msw/webview_ie.cpp @@ -1762,7 +1762,7 @@ HRESULT STDMETHODCALLTYPE VirtualProtocol::CombineUrl( } HRESULT STDMETHODCALLTYPE VirtualProtocol::ParseUrl( - LPCWSTR pwzUrl, PARSEACTION ParseAction, + LPCWSTR pwzUrl, wxPARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved) @@ -1777,8 +1777,8 @@ HRESULT STDMETHODCALLTYPE VirtualProtocol::ParseUrl( switch (ParseAction) { - case PARSE_SECURITY_URL: - case PARSE_SECURITY_DOMAIN: + case wxPARSE_SECURITY_URL: + case wxPARSE_SECURITY_DOMAIN: { LPWSTR Result = L"http://localhost"; size_t Len = wcslen(Result); @@ -1806,7 +1806,7 @@ HRESULT STDMETHODCALLTYPE VirtualProtocol::CompareUrl( } HRESULT STDMETHODCALLTYPE VirtualProtocol::QueryInfo( - LPCWSTR pwzUrl, QUERYOPTION OueryOption, + LPCWSTR pwzUrl, wxQUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)