From a1f19a3b143565777eea9ccbf77bcbd9c6aaf4c6 Mon Sep 17 00:00:00 2001 From: datadiode Date: Sun, 3 Sep 2023 04:40:16 +0200 Subject: [PATCH] Reuse most of the There Edge Browser Proxy to implement the OpennessWebView2 Control --- BrowserProxy/BrowserProxy.cpp | 562 +++++++----------------------- BrowserProxy/BrowserProxy.h | 225 +++++++----- BrowserProxy/BrowserProxy.idl | 8 +- BrowserProxy/BrowserProxy.rgs | 21 +- BrowserProxy/BrowserProxy.vcxproj | 6 +- README.md | 10 +- 6 files changed, 299 insertions(+), 533 deletions(-) diff --git a/BrowserProxy/BrowserProxy.cpp b/BrowserProxy/BrowserProxy.cpp index a41a044..0cd5930 100644 --- a/BrowserProxy/BrowserProxy.cpp +++ b/BrowserProxy/BrowserProxy.cpp @@ -24,7 +24,11 @@ #include "BrowserProxy_i.h" #include "BrowserProxy.h" -BrowserProxyModule g_AtlModule; +BEGIN_OBJECT_MAP(ObjectMap) + OBJECT_ENTRY(CLSID_ThereEdgeWebBrowser, BrowserProxyModule) +END_OBJECT_MAP() + +CComModule g_AtlModule; HINSTANCE g_Instance; void Log(const WCHAR *format, ...) @@ -63,11 +67,18 @@ void ReportError(HWND wnd, const WCHAR *format, ...) extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { - g_Instance = hInstance; - return g_AtlModule.DllMain(dwReason, lpReserved); + if (dwReason == DLL_PROCESS_ATTACH) + { + g_Instance = hInstance; + g_AtlModule.Init(ObjectMap, (HINSTANCE)hInstance, &LIBID_BrowserProxyLib); + } + else if (dwReason == DLL_PROCESS_DETACH) + { + g_AtlModule.Term(); + } + return TRUE; } -__control_entrypoint(DllExport) STDAPI DllCanUnloadNow() { return g_AtlModule.DllCanUnloadNow(); @@ -75,13 +86,6 @@ STDAPI DllCanUnloadNow() STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { - if (IsEqualIID(riid, IID_IClassFactory)) - { - g_AtlModule.AddRef(); - *ppv = static_cast(&g_AtlModule); - return S_OK; - } - return g_AtlModule.DllGetClassObject(rclsid, riid, ppv); } @@ -120,16 +124,11 @@ STDAPI DllInstall(BOOL bInstall, _In_opt_ LPCWSTR pszCmdLine) } BrowserProxyModule::BrowserProxyModule(): - m_refCount(1), - m_size(), - m_wnd(nullptr), m_url(), m_proxyVersion(), m_browserVersion(), m_userDataFolder(), m_browserEvents(), - m_unknownSite(), - m_clientSite(), m_environment(), m_controller(), m_view(), @@ -151,6 +150,7 @@ BrowserProxyModule::BrowserProxyModule(): m_ready(false), m_visible(true) { + m_bWindowOnly = TRUE; } BrowserProxyModule::~BrowserProxyModule() @@ -183,364 +183,163 @@ BrowserProxyModule::~BrowserProxyModule() m_settingsRequestHandler.Release(); } -HRESULT STDMETHODCALLTYPE BrowserProxyModule::QueryInterface(REFIID riid, void **object) -{ - if (IsEqualIID(riid, IID_IUnknown)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - if (IsEqualIID(riid, IID_IConnectionPointContainer)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - if (IsEqualIID(riid, IID_IOleObject)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - if (IsEqualIID(riid, IID_IObjectWithSite)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - if (IsEqualIID(riid, IID_IOleInPlaceActiveObject)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - if (IsEqualIID(riid, IID_IViewObjectEx)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - if (IsEqualIID(riid, IID_ISupportErrorInfo)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - if (IsEqualIID(riid, IID_IDispatch)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - if (IsEqualIID(riid, IID_IThereEdgeWebBrowser2)) - { - AddRef(); - *object = static_cast(this); - return S_OK; - } - - *object = nullptr; - return E_NOINTERFACE; -} - -ULONG STDMETHODCALLTYPE BrowserProxyModule::AddRef() -{ - return ++m_refCount; -} - -ULONG STDMETHODCALLTYPE BrowserProxyModule::Release() -{ - ULONG refCount = m_refCount--; - - if (refCount == 0) - delete this; - - return refCount; -} - -HRESULT STDMETHODCALLTYPE BrowserProxyModule::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) -{ - if (IsEqualIID(riid, IID_IUnknown)) - { - auto module = new BrowserProxyModule(); - if (module == nullptr) - return E_FAIL; - - *ppv = static_cast(module); - return S_OK; - } - - return E_NOINTERFACE; -} - -HRESULT STDMETHODCALLTYPE BrowserProxyModule::LockServer(BOOL fLock) +HRESULT STDMETHODCALLTYPE BrowserProxyModule::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj) { - if (fLock) - m_nLockCnt++; - else - m_nLockCnt--; - return S_OK; } -HRESULT STDMETHODCALLTYPE BrowserProxyModule::FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) +bool BrowserProxyModule::InIDE() { - if (IsEqualIID(riid, DIID_IThereEdgeWebBrowserEvents2)) - { - AddRef(); - *ppCP = static_cast(this); - return S_OK; - } - - return E_NOINTERFACE; -} - -HRESULT STDMETHODCALLTYPE BrowserProxyModule::Advise(IUnknown *pUnkSink, DWORD *pdwCookie) -{ - if (pUnkSink == nullptr || pdwCookie == nullptr) - return E_INVALIDARG; - - if (SUCCEEDED(pUnkSink->QueryInterface(&m_browserEvents))) - { - *pdwCookie = (DWORD)&m_browserEvents; - return S_OK; - } - - return E_FAIL; + BOOL bUserMode = TRUE; + return SUCCEEDED(GetAmbientUserMode(bUserMode)) && !bUserMode; } -HRESULT STDMETHODCALLTYPE BrowserProxyModule::Unadvise(DWORD dwCookie) +HRESULT BrowserProxyModule::OnDraw(ATL_DRAWINFO& di) { - if (dwCookie == (DWORD)&m_browserEvents && m_browserEvents != nullptr) + if (InIDE()) { - m_browserEvents.Release(); - return S_OK; - } - - return E_FAIL; -} - -HRESULT STDMETHODCALLTYPE BrowserProxyModule::SetClientSite(IOleClientSite *pClientSite) -{ - m_clientSite = pClientSite; - return S_OK; -} + RECT& rc = *(RECT*)di.prcBounds; + Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom); -HRESULT STDMETHODCALLTYPE BrowserProxyModule::GetClientSite(IOleClientSite **ppClientSite) -{ - if (ppClientSite == nullptr) - return E_INVALIDARG; + SetTextAlign(di.hdcDraw, TA_LEFT | TA_BASELINE); - if (FAILED(m_clientSite.CopyTo(ppClientSite))) - return E_FAIL; + int x = 5; + int y = 15; - return S_OK; -} + CComBSTR text; + text += L"OpennessWebView2 v"; + text += m_proxyVersion; + text += L" Control - Design Mode"; -HRESULT STDMETHODCALLTYPE BrowserProxyModule::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj) -{ - return S_OK; -} - -HRESULT STDMETHODCALLTYPE BrowserProxyModule::Close(DWORD dwSaveOption) -{ - if (m_controller != nullptr) - m_controller->Close(); + MoveToEx(di.hdcDraw, x, y, nullptr); + TextOut(di.hdcDraw, x, y, text, text.Length()); + } - Release(); return S_OK; } -HRESULT STDMETHODCALLTYPE BrowserProxyModule::DoVerb(LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect) +LRESULT BrowserProxyModule::OnCreate(UINT, WPARAM, LPARAM, BOOL&) { - switch (iVerb) + if (HRSRC source = FindResource(g_Instance, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION)) { - case OLEIVERB_INPLACEACTIVATE: + if (HGLOBAL resource = LoadResource(g_Instance, source)) { - if (m_environment != nullptr) - return S_OK; - - if (hwndParent == nullptr) - return E_INVALIDARG; - - if (pActiveSite == nullptr) - return E_INVALIDARG; - - if (lprcPosRect == nullptr) - return E_INVALIDARG; - - m_wnd = hwndParent; - - SetRect(*lprcPosRect); - + if (void *data = LockResource(resource)) { - HRSRC source = FindResource(g_Instance, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION); - if (source != nullptr) + VS_FIXEDFILEINFO *version = nullptr; + UINT size = 0; + if (VerQueryValue(data, L"\\", (void**)&version, &size) && version != nullptr && size >= sizeof(VS_FIXEDFILEINFO)) { - HGLOBAL resource = LoadResource(g_Instance, source); - if (resource != nullptr) - { - void *data = LockResource(resource); - if (data != nullptr) - { - VS_FIXEDFILEINFO *version = nullptr; - UINT size = 0; - if (VerQueryValue(data, L"\\", (void**)&version, &size) && version != nullptr && size >= sizeof(VS_FIXEDFILEINFO)) - { - WCHAR value[100]; - _snwprintf_s(value, _countof(value), L"%u.%u.%u", - version->dwFileVersionMS >> 16 & 0xFFFF, - version->dwFileVersionMS & 0xFFFF, - version->dwFileVersionLS >> 16 & 0xFFFF); - m_proxyVersion = value; - } - } - } + WCHAR value[100]; + _snwprintf_s(value, _countof(value), L"%u.%u.%u.%u", + version->dwFileVersionMS >> 16 & 0xFFFF, + version->dwFileVersionMS & 0xFFFF, + version->dwFileVersionLS >> 16 & 0xFFFF, + version->dwFileVersionLS & 0xFFFF); + m_proxyVersion = value; } } + } + } + if (!InIDE()) + { + WCHAR userDataFolder[MAX_PATH] = {0}; + if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, userDataFolder)) && userDataFolder[0] != 0) + { + WCHAR executingFile[MAX_PATH] = { 0 }; + GetModuleFileName(g_Instance, executingFile, _countof(executingFile)); + if (PathAppend(userDataFolder, PathFindFileName(executingFile))) { - WCHAR userDataFolder[MAX_PATH] = {0}; - if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_LOCAL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, userDataFolder)) && userDataFolder[0] != 0) + CreateDirectory(userDataFolder, nullptr); + GetModuleFileName(nullptr, executingFile, _countof(executingFile)); + if (PathAppend(userDataFolder, PathFindFileName(executingFile))) { - if (PathAppend(userDataFolder, L"There")) - { - CreateDirectory(userDataFolder, nullptr); - if (PathAppend(userDataFolder, L"Edge")) - { - CreateDirectory(userDataFolder, nullptr); - m_userDataFolder = userDataFolder; - } - } + CreateDirectory(userDataFolder, nullptr); + m_userDataFolder = userDataFolder; } } - - HRESULT rc = CreateCoreWebView2EnvironmentWithOptions(nullptr, m_userDataFolder, nullptr, this); - if (FAILED(rc)) + } + HRESULT rc = CreateCoreWebView2EnvironmentWithOptions(nullptr, m_userDataFolder, nullptr, this); + if (FAILED(rc)) + { + switch (rc) { - switch (rc) + case HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED): { - case HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED): - { - ReportError(hwndParent, L"The Edge application path was used in the browser executable folder."); - break; - } - case HRESULT_FROM_WIN32(ERROR_INVALID_STATE): - { - ReportError(hwndParent, L"The specified options do not match the options of the WebViews that are currently running in the shared browser process."); - break; - } - case HRESULT_FROM_WIN32(ERROR_DISK_FULL): - { - ReportError(hwndParent, L"Too many previous WebView2 Runtime versions exist."); - break; - } - case HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED): - { - ReportError(hwndParent, L"The Webview depends upon an installed WebView2 Runtime version and it is uninstalled."); - break; - } - case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND): - { - ReportError(hwndParent, L"Could not find an Edge installation."); - break; - } - case HRESULT_FROM_WIN32(ERROR_FILE_EXISTS): - { - ReportError(hwndParent, L"The user data folder cannot be created because a file with the same name already exists."); - break; - } - case E_ACCESSDENIED: - { - ReportError(hwndParent, L"Unable to create the user data folder."); - break; - } - case E_FAIL: - { - ReportError(hwndParent, L"The Edge runtime is unable to start."); - break; - } - default: - { - ReportError(hwndParent, L"Unable to create a WebView2 environment: 0x%08lx", rc); - break; - } + ReportError(m_hWnd, L"The Edge application path was used in the browser executable folder."); + break; + } + case HRESULT_FROM_WIN32(ERROR_INVALID_STATE): + { + ReportError(m_hWnd, L"The specified options do not match the options of the WebViews that are currently running in the shared browser process."); + break; + } + case HRESULT_FROM_WIN32(ERROR_DISK_FULL): + { + ReportError(m_hWnd, L"Too many previous WebView2 Runtime versions exist."); + break; + } + case HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED): + { + ReportError(m_hWnd, L"The Webview depends upon an installed WebView2 Runtime version and it is uninstalled."); + break; + } + case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND): + { + ReportError(m_hWnd, L"Could not find an Edge installation."); + break; + } + case HRESULT_FROM_WIN32(ERROR_FILE_EXISTS): + { + ReportError(m_hWnd, L"The user data folder cannot be created because a file with the same name already exists."); + break; + } + case E_ACCESSDENIED: + { + ReportError(m_hWnd, L"Unable to create the user data folder."); + break; + } + case E_FAIL: + { + ReportError(m_hWnd, L"The Edge runtime is unable to start."); + break; + } + default: + { + ReportError(m_hWnd, L"Unable to create a WebView2 environment: 0x%08lx", rc); + break; } - - return E_FAIL; } - - return S_OK; } - - default: - return E_NOTIMPL; } -} - -HRESULT STDMETHODCALLTYPE BrowserProxyModule::SetExtent(DWORD dwDrawAspect, SIZEL *psizel) -{ - if (dwDrawAspect != DVASPECT_CONTENT || psizel == nullptr) - return E_INVALIDARG; - - SetSize(*psizel); - return S_OK; -} - -HRESULT STDMETHODCALLTYPE BrowserProxyModule::GetExtent(DWORD dwDrawAspect, SIZEL *psizel) -{ - if (dwDrawAspect != DVASPECT_CONTENT || psizel == nullptr) - return E_INVALIDARG; - *psizel = m_size; - return S_OK; + return 0; } -HRESULT STDMETHODCALLTYPE BrowserProxyModule::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus) +LRESULT BrowserProxyModule::OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled) { - if (dwAspect != DVASPECT_CONTENT || pdwStatus == nullptr) - return E_INVALIDARG; - - *pdwStatus = 0; - return S_OK; -} - -HRESULT STDMETHODCALLTYPE BrowserProxyModule::SetSite(IUnknown *pUnkSite) -{ - if (pUnkSite == nullptr) - return E_INVALIDARG; + if (m_controller != nullptr) + m_controller->Close(); - m_unknownSite = pUnkSite; - return S_OK; + bHandled = FALSE; + return 0; } -HRESULT STDMETHODCALLTYPE BrowserProxyModule::GetSite(REFIID riid, void **ppvSite) +LRESULT BrowserProxyModule::OnSize(UINT, WPARAM, LPARAM, BOOL&) { - if (ppvSite == nullptr) - return E_INVALIDARG; - - if (FAILED(m_unknownSite.CopyTo((IUnknown**)ppvSite))) - return E_FAIL; - - return S_OK; + if (m_controller) + { + RECT bounds; + GetClientRect(&bounds); + m_controller->put_Bounds(bounds); + } + return 0; } -HRESULT STDMETHODCALLTYPE BrowserProxyModule::GetWindow(HWND *phwnd) +LRESULT BrowserProxyModule::OnEraseBkgnd(UINT, WPARAM, LPARAM, BOOL&) { - if (phwnd == nullptr) - return E_INVALIDARG; - - *phwnd = m_wnd; - return S_OK; + return 1; } HRESULT STDMETHODCALLTYPE BrowserProxyModule::GoBack() @@ -703,31 +502,8 @@ HRESULT STDMETHODCALLTYPE BrowserProxyModule::Invoke(HRESULT errorCode, ICoreWeb CoTaskMemFree(version); } - for (HWND wnd = m_wnd; wnd != nullptr; wnd = GetParent(wnd)) - { - if (GetWindowLong(wnd, GWL_STYLE) & WS_CHILDWINDOW) - continue; - - WCHAR className[100]; - if (GetClassName(wnd, className, _countof(className)) == 0) - break; - - if (wcscmp(className, L"ThereTopLevelMdiWindowClass") != 0) - break; - - WCHAR currentTitle[250]; - if (GetWindowText(wnd, currentTitle, _countof(currentTitle)) > 0 && wcsstr(currentTitle, L"Edge") == nullptr) - { - WCHAR extendedTitle[250]; - _snwprintf_s(extendedTitle, _countof(extendedTitle), L"%s (Edge %s %s)", currentTitle, m_proxyVersion.m_str, m_browserVersion.m_str); - SetWindowText(wnd, extendedTitle); - } - - break; - } - m_environment = environment; - m_environment->CreateCoreWebView2Controller(m_wnd, this); + m_environment->CreateCoreWebView2Controller(m_hWnd, this); return S_OK; } @@ -761,7 +537,7 @@ HRESULT STDMETHODCALLTYPE BrowserProxyModule::Invoke(HRESULT errorCode, ICoreWeb settings->put_IsWebMessageEnabled(false); RECT bounds; - GetClientRect(m_wnd, &bounds); + GetClientRect(&bounds); m_controller->put_Bounds(bounds); m_controller->put_ShouldDetectMonitorScaleChanges(false); @@ -847,7 +623,6 @@ HRESULT STDMETHODCALLTYPE BrowserProxyModule::Invoke(HRESULT errorCode, ICoreWeb } ).Get(), &m_downloadStartingToken); - GetStartPage(); ProcessDeferral(); if (FAILED(Navigate())) @@ -916,7 +691,7 @@ HRESULT BrowserProxyModule::OnNavigationStarting(ICoreWebView2 *sender, ICoreWe if (VoiceTrainerProxy::Validate(m_url)) { CComPtr voiceTrainerProxy(new VoiceTrainerProxy()); - if (voiceTrainerProxy != nullptr && SUCCEEDED(voiceTrainerProxy->Init(m_wnd, sender))) + if (voiceTrainerProxy != nullptr && SUCCEEDED(voiceTrainerProxy->Init(m_hWnd, sender))) { m_voiceTrainerProxy = voiceTrainerProxy; settings->put_IsWebMessageEnabled(true); @@ -1172,7 +947,7 @@ HRESULT BrowserProxyModule::OnWebResourceRequested(ICoreWebView2 *sender, ICoreW } if (m_settingsRequestHandler != nullptr && SettingsRequestHandler::Validate(burl)) - return m_settingsRequestHandler->HandleRequest(burl, args, m_wnd); + return m_settingsRequestHandler->HandleRequest(burl, args, m_hWnd); return S_OK; } @@ -1388,52 +1163,6 @@ HRESULT BrowserProxyModule::InvokeBrowserEvent(DISPID id, DISPPARAMS ¶ms, VA return S_OK; } -HRESULT BrowserProxyModule::SetSize(const SIZE &size) -{ - RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = rect.left + size.cx; - rect.bottom = rect.top + size.cy; - - return SetRect(rect); -} - -HRESULT BrowserProxyModule::SetRect(const RECT &rect) -{ - UINT flags = SWP_NOMOVE; - - LONG width = rect.right > rect.left ? rect.right - rect.left : 1; - LONG height= rect.bottom > rect.top ? rect.bottom - rect.top : 1; - - if (width == m_size.cx && height == m_size.cy) - flags |= SWP_NOSIZE; - - if (flags == (SWP_NOMOVE | SWP_NOSIZE)) - return S_OK; - - m_size.cx = width; - m_size.cy = height; - - if (m_wnd == nullptr) - return S_OK; - - if (m_controller != nullptr) - { - if ((flags & SWP_NOMOVE) == 0) - m_controller->NotifyParentWindowPositionChanged(); - - if ((flags & SWP_NOSIZE) == 0) - { - RECT bounds; - GetClientRect(m_wnd, &bounds); - m_controller->put_Bounds(bounds); - } - } - - return S_OK; -} - HRESULT BrowserProxyModule::SetVisibility(BOOL visible) { if (visible == m_visible) @@ -1660,32 +1389,3 @@ HRESULT BrowserProxyModule::ProcessDeferral() return S_OK; } - -HRESULT BrowserProxyModule::GetStartPage(const WCHAR *path) -{ - if (m_url.Length() > 0 || m_newWindowDeferral != nullptr) - return S_OK; - - if (path == nullptr) - { - if (GetStartPage(L"Software\\There.com\\There\\Edge\\") == S_OK) - return S_OK; - - if (GetStartPage(L"Software\\Microsoft\\Internet Explorer\\Main\\") == S_OK) - return S_OK; - - return S_FALSE; - } - - WCHAR url[INTERNET_MAX_URL_LENGTH]; - DWORD length = _countof(url); - if (RegGetValue(HKEY_CURRENT_USER, path, L"Start Page", RRF_RT_REG_SZ, nullptr, &url, &length) == ERROR_SUCCESS) - { - if (length > 0 && wcscmp(url, L"about:blank") != 0) - m_url = url; - - return S_OK; - } - - return S_FALSE; -} \ No newline at end of file diff --git a/BrowserProxy/BrowserProxy.h b/BrowserProxy/BrowserProxy.h index 313d4d2..96b386c 100644 --- a/BrowserProxy/BrowserProxy.h +++ b/BrowserProxy/BrowserProxy.h @@ -1,96 +1,161 @@ #pragma once using namespace ATL; -using namespace Microsoft::WRL; void Log(const WCHAR *format, ...); -class BrowserProxyModule: public ATL::CAtlDllModuleT, - public IClassFactoryEx, - public IConnectionPointContainer, - public IConnectionPoint, - public IOleObject, - public IObjectWithSite, - public IOleInPlaceActiveObject, - public IViewObjectEx, - public ISupportErrorInfo, - public IThereEdgeWebBrowser2, +class CDispInvoke +{ +public: + static UINT const WM_DISPINVOKE = WM_APP + 1; + CDispInvoke + ( + IDispatch* p, + DISPID dispidMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pdispparams, + VARIANT* pvarResult, + EXCEPINFO* pexcepinfo, + UINT* puArgErr + ) + : p(p) + , dispidMember(dispidMember) + , riid(riid) + , lcid(lcid) + , wFlags(wFlags) + , pdispparams(pdispparams) + , pvarResult(pvarResult) + , pexcepinfo(pexcepinfo) + , puArgErr(puArgErr) + { + } + LRESULT Invoke() + { + return p->Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); + } + HRESULT Invoke(HWND hwnd) + { + return static_cast(SendMessage(hwnd, WM_DISPINVOKE, 0, reinterpret_cast(this))); + } + static LRESULT OnDispInvoke(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + return reinterpret_cast(lParam)->Invoke(); + } +private: + IDispatch* const p; + DISPID const dispidMember; + REFIID riid; + LCID const lcid; + WORD const wFlags; + DISPPARAMS* const pdispparams; + VARIANT* const pvarResult; + EXCEPINFO* const pexcepinfo; + UINT* const puArgErr; +}; + +class BrowserProxyLicense +{ +protected: + static BOOL VerifyLicenseKey(BSTR bstr) + { + return wcscmp(bstr, L"fX5xiyLkhf1hCQ6gh9Zrsw") == 0; + } + static BOOL GetLicenseKey(DWORD, BSTR* pBstr) + { + *pBstr = SysAllocString(L"fX5xiyLkhf1hCQ6gh9Zrsw"); + return TRUE; + } + static BOOL IsLicenseValid() { return TRUE; } +}; + +class BrowserProxyModule: public CComObjectRootEx, + public CComControl, + public IOleControlImpl, + public IOleObjectImpl, + public IOleInPlaceActiveObjectImpl, + public IViewObjectExImpl, + public IOleInPlaceObjectWindowlessImpl, + public IPersistStorageImpl, + public IPersistStreamInitImpl, + public ISupportErrorInfoImpl<&IID_IThereEdgeWebBrowser>, + public IDispatchImpl, + public CComCoClass, public ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler, public ICoreWebView2CreateCoreWebView2ControllerCompletedHandler { public: - DECLARE_LIBID(LIBID_BrowserProxyLib) - DECLARE_REGISTRY_APPID_RESOURCEID(IDR_BROWSERPROXY, "{E792F884-FF4C-4563-92FE-ADAEA759F2EA}") + DECLARE_CLASSFACTORY2(BrowserProxyLicense) + DECLARE_REGISTRY_RESOURCEID(IDR_BROWSERPROXY) + + DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE | + OLEMISC_CANTLINKINSIDE | + OLEMISC_INSIDEOUT | + OLEMISC_ACTIVATEWHENVISIBLE | + OLEMISC_SETCLIENTSITEFIRST) BrowserProxyModule(); virtual ~BrowserProxyModule(); - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object) override; - virtual ULONG STDMETHODCALLTYPE AddRef() override; - virtual ULONG STDMETHODCALLTYPE Release() override; + BEGIN_COM_MAP(BrowserProxyModule) + COM_INTERFACE_ENTRY(IThereEdgeWebBrowser) + COM_INTERFACE_ENTRY2(IDispatch, IThereEdgeWebBrowser) + COM_INTERFACE_ENTRY(IViewObjectEx) + COM_INTERFACE_ENTRY(IViewObject2) + COM_INTERFACE_ENTRY(IViewObject) + COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless) + COM_INTERFACE_ENTRY(IOleInPlaceObject) + COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless) + COM_INTERFACE_ENTRY(IOleInPlaceActiveObject) + COM_INTERFACE_ENTRY(IOleControl) + COM_INTERFACE_ENTRY(IOleObject) + COM_INTERFACE_ENTRY(IPersistStorage) + COM_INTERFACE_ENTRY(IPersistStreamInit) + COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) + END_COM_MAP() + + BEGIN_PROP_MAP(BrowserProxyModule) + PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4) + PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4) + END_PROP_MAP() + + BEGIN_MSG_MAP(BrowserProxyModule) + CHAIN_MSG_MAP(CComControl) + MESSAGE_HANDLER(CDispInvoke::WM_DISPINVOKE, CDispInvoke::OnDispInvoke) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd) + END_MSG_MAP() + + HRESULT IPersistStreamInit_Load(LPSTREAM, ATL_PROPMAP_ENTRY const*) { return S_OK; } + + bool InIDE(); + HRESULT OnDraw(ATL_DRAWINFO& di); protected: - virtual HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) override; - virtual HRESULT STDMETHODCALLTYPE CreateInstanceWithContext(IUnknown *punkContext, IUnknown *punkOuter, REFIID riid, void **ppv) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) override; - virtual HRESULT STDMETHODCALLTYPE EnumConnectionPoints(IEnumConnectionPoints **ppEnum) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) override; - virtual HRESULT STDMETHODCALLTYPE GetConnectionInterface(IID *pIID) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetConnectionPointContainer(IConnectionPointContainer **ppCPC) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE Advise(IUnknown *pUnkSink, DWORD *pdwCookie) override; - virtual HRESULT STDMETHODCALLTYPE Unadvise(DWORD dwCookie) override; - virtual HRESULT STDMETHODCALLTYPE EnumConnections(IEnumConnections **ppEnum) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE SetClientSite(IOleClientSite *pClientSite) override; - virtual HRESULT STDMETHODCALLTYPE GetClientSite(IOleClientSite **ppClientSite) override; + LRESULT OnCreate(UINT, WPARAM, LPARAM, BOOL&); + LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL&); + LRESULT OnSize(UINT, WPARAM, LPARAM, BOOL&); + LRESULT OnEraseBkgnd(UINT, WPARAM, LPARAM, BOOL&); + + STDMETHOD(Invoke)( + DISPID dispidMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS* pdispparams, + VARIANT* pvarResult, + EXCEPINFO* pexcepinfo, + UINT* puArgErr) + { + return GetCurrentThreadId() != GetWindowThreadProcessId(m_hWnd, NULL) ? + CDispInvoke(this, dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr).Invoke(m_hWnd) : + IDispatchImpl::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); + } + virtual HRESULT STDMETHODCALLTYPE SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj) override; - virtual HRESULT STDMETHODCALLTYPE Close(DWORD dwSaveOption) override; - virtual HRESULT STDMETHODCALLTYPE SetMoniker(DWORD dwWhichMoniker, IMoniker *pmk) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE InitFromData(IDataObject *pDataObject, BOOL fCreation, DWORD dwReserved) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetClipboardData(DWORD dwReserved, IDataObject **ppDataObject) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE DoVerb(LONG iVerb, LPMSG lpmsg, IOleClientSite *pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect) override; - virtual HRESULT STDMETHODCALLTYPE EnumVerbs(IEnumOLEVERB **ppEnumOleVerb) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE Update() override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE IsUpToDate() override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetUserClassID(CLSID *pClsid) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE SetExtent(DWORD dwDrawAspect, SIZEL *psizel) override; - virtual HRESULT STDMETHODCALLTYPE GetExtent(DWORD dwDrawAspect, SIZEL *psizel) override; - virtual HRESULT STDMETHODCALLTYPE Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE EnumAdvise(IEnumSTATDATA **ppenumAdvise) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus) override; - virtual HRESULT STDMETHODCALLTYPE SetColorScheme(LOGPALETTE *pLogpal) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite) override; - virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite) override; - virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd) override; - virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL fActivate) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL fActivate) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, - HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, - BOOL (STDMETHODCALLTYPE *pfnContinue)(ULONG_PTR dwContinue), ULONG_PTR dwContinue) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, - HDC hicTargetDev, LOGPALETTE **ppColorSet) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE Unfreeze(DWORD dwFreeze) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetExtent(DWORD dwDrawAspect, LONG lindex, DVTARGETDEVICE *ptd, LPSIZEL lpsizel) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetRect(DWORD dwAspect, LPRECTL pRect) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetViewStatus(DWORD *pdwStatus) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE QueryHitPoint(DWORD dwAspect, LPCRECT pRectBounds, POINT ptlLoc, LONG lCloseHint, DWORD *pHitResult) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE QueryHitRect(DWORD dwAspect, LPCRECT pRectBounds, LPCRECT pRectLoc, LONG lCloseHint, DWORD *pHitResult) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetNaturalExtent(DWORD dwAspect, LONG lindex, DVTARGETDEVICE *ptd, - HDC hicTargetDev, DVEXTENTINFO *pExtentInfo, LPSIZEL pSizel) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE InterfaceSupportsErrorInfo(REFIID riid) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) override {return E_NOTIMPL;} - virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, - VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) override {return E_NOTIMPL;} virtual HRESULT STDMETHODCALLTYPE GoBack() override; virtual HRESULT STDMETHODCALLTYPE GoForward() override; virtual HRESULT STDMETHODCALLTYPE GoHome() override; @@ -172,27 +237,19 @@ class BrowserProxyModule: public ATL::CAtlDllModuleT, HRESULT OnDownloadStarting(ICoreWebView2 *sender, ICoreWebView2DownloadStartingEventArgs *args); HRESULT Navigate(); HRESULT InvokeBrowserEvent(DISPID id, DISPPARAMS &args, VARIANT *result = nullptr); - HRESULT SetSize(const SIZE &size); - HRESULT SetRect(const RECT &rect); HRESULT SetVisibility(BOOL visible); HRESULT ForwardCookie(ICoreWebView2CookieManager *cookieManager, const WCHAR *url, const WCHAR *name, const WCHAR *domain, const WCHAR *path); HRESULT ApplyScript(ICoreWebView2 *view, LONG id); HRESULT SetDeferral(ICoreWebView2NewWindowRequestedEventArgs *args); HRESULT ProcessDeferral(); - HRESULT GetStartPage(const WCHAR *path = nullptr); protected: - ULONG m_refCount; - SIZE m_size; - HWND m_wnd; CComBSTR m_url; CComBSTR m_proxyVersion; CComBSTR m_browserVersion; CComBSTR m_userDataFolder; CComPtr m_browserEvents; - CComPtr m_unknownSite; - CComPtr m_clientSite; CComPtr m_environment; CComPtr m_controller; CComPtr m_view; diff --git a/BrowserProxy/BrowserProxy.idl b/BrowserProxy/BrowserProxy.idl index 96ce063..4c7c3cf 100644 --- a/BrowserProxy/BrowserProxy.idl +++ b/BrowserProxy/BrowserProxy.idl @@ -5,7 +5,7 @@ import "docobj.idl"; #include "exdispid.h" [ - uuid(E792F884-FF4C-4563-92FE-ADAEA759F2EA), + uuid(78B1F56A-FBF7-476F-86A7-E6C5C2231A6F), version(1.0), ] library BrowserProxyLib @@ -20,7 +20,7 @@ library BrowserProxyLib [ odl, uuid(2170EFE4-F488-4F5C-A844-469080351EC4), - helpstring("Browser Proxy"), + helpstring("OpennessWebView2 Control"), dual, oleautomation, hidden @@ -330,8 +330,8 @@ library BrowserProxyLib } [ - uuid(4D5AA1D8-B2D9-49D0-860E-8DAF2EC2CF0C), - helpstring("There Edge Browser Proxy") + uuid(C5AEB42F-7900-41E7-B86B-F0A9DF8A4780), + helpstring("OpennessWebView2 Control") ] coclass ThereEdgeWebBrowser { diff --git a/BrowserProxy/BrowserProxy.rgs b/BrowserProxy/BrowserProxy.rgs index 275e09b..4bc5ded 100644 --- a/BrowserProxy/BrowserProxy.rgs +++ b/BrowserProxy/BrowserProxy.rgs @@ -1,17 +1,26 @@ HKCR { + Openness.WebView2 = s 'OpennessWebView2 Control' + { + CLSID = s '{C5AEB42F-7900-41E7-B86B-F0A9DF8A4780}' + } NoRemove CLSID { - ForceRemove {4D5AA1D8-B2D9-49D0-860E-8DAF2EC2CF0C} = s 'There Edge Browser Proxy' + ForceRemove {C5AEB42F-7900-41E7-B86B-F0A9DF8A4780} = s 'OpennessWebView2 Control' { - ForceRemove Programmable + ForceRemove 'Programmable' + ForceRemove 'Control' + ForceRemove 'Insertable' + 'MiscStatus' = s '0' + { + '1' = s '131473' + } InprocServer32 = s '%MODULE%' { - val ThreadingModel = s 'Apartment' + val ThreadingModel = s 'Both' } - ProgID = s 'ThereEdge.BrowserProxy.1' - VersionIndependentProgID = s 'ThereEdge.BrowserProxy' - TypeLib = s '{E792F884-FF4C-4563-92FE-ADAEA759F2EA}' + ProgID = s 'Openness.WebView2' + TypeLib = s '{78B1F56A-FBF7-476F-86A7-E6C5C2231A6F}' Version = s '1.0' } } diff --git a/BrowserProxy/BrowserProxy.vcxproj b/BrowserProxy/BrowserProxy.vcxproj index 85ed717..8a4bc4d 100644 --- a/BrowserProxy/BrowserProxy.vcxproj +++ b/BrowserProxy/BrowserProxy.vcxproj @@ -57,19 +57,19 @@ true true - BrowserProxy + OpennessWebView2 $(SolutionDir)BrowserProxy\$(Configuration)\ true false - BrowserProxy + OpennessWebView2 $(SolutionDir)BrowserProxy\$(Configuration)\ true false - BrowserProxy + OpennessWebView2 $(SolutionDir)BrowserProxy\$(Configuration)\ diff --git a/README.md b/README.md index ea11b05..80dc0dd 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -# ActiveX proxy to Edge WebView2 +# OpennessWebView2 Control -This is a pair of ActiveX proxies to [Microsoft Edge WebView2](https://docs.microsoft.com/en-us/microsoft-edge/webview2/) for the [There](https://www.there.com/) client as a replacement for both the [Flash](https://www.adobe.com/products/flashplayer/end-of-life.html) controls and Internet Explorer WebBrowser control. +[![StandWithUkraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) -The [Microsoft Edge WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) needs to be installed to use these controls. +This ActiveX control embeds [Microsoft Edge WebView2](https://docs.microsoft.com/en-us/microsoft-edge/webview2/) into SIMATIC WinCC Runtime Advanced. + +The [Microsoft Edge WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) needs to be installed to use this control. ## Building from source @@ -16,5 +18,3 @@ Install [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) with the fo * Windows 10 SDK (10.0.19041.0) * Python language support * Python 3 64-bit (3.9.13) - -![Screenshot](https://media.fotki.com/2v2aKZw88x3JhYT.png) \ No newline at end of file