diff options
author | Fredrik Orderud <fredrik.orderud@ge.com> | 2018-10-07 12:54:09 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2018-10-19 08:03:57 +0000 |
commit | cf0e85184dbba6b9d5feb106277d323521d18b0c (patch) | |
tree | 7d1b3e7b26ce47f6dc975b53b60430e83289c285 /src | |
parent | d20eb95f227a841c3d4c319c2cc146b3caa94f5c (diff) | |
download | qtactiveqt-cf0e85184dbba6b9d5feb106277d323521d18b0c.tar.gz |
ActiveQt: Make window parenting sandbox compatible
In QAxServerBase, CreateWindow currently fails with ERROR_ACCESS_DENIED if the container
is running in a higher integrity process. This is caused by the low integrity process
not being permitted to create a child window to the high integrity container window.
Add fallback logic to instead create the control window stand-alone, instead of being a
child window, and then "re-parent" it from the container afterwards. This is following
the same pattern as Google Chrome.
Task-number: QTBUG-70983
Change-Id: I76fed85226bf5631343ea7d50b16e03d2d1b5d8c
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/activeqt/container/qaxwidget.cpp | 24 | ||||
-rw-r--r-- | src/activeqt/control/qaxserverbase.cpp | 13 |
2 files changed, 36 insertions, 1 deletions
diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index b25e4b2..a28c64f 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -695,10 +695,32 @@ bool QAxClientSite::activateObject(bool initialized, const QByteArray &data) RECT rcPos = qaxQRect2Rect(QRect(qaxNativeWidgetPosition(host), qaxToNativeSize(host, sizehint))); + const HWND hostWnd = reinterpret_cast<HWND>(host->winId()); m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, static_cast<IOleClientSite *>(this), 0, - reinterpret_cast<HWND>(host->winId()), + hostWnd, &rcPos); + HWND controlWnd = {}; + { + IOleWindow *oleWindow = nullptr; + m_spOleObject->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow)); + if (oleWindow) { + oleWindow->GetWindow(&controlWnd); + oleWindow->Release(); + } + } + + if (controlWnd && !GetParent(controlWnd)) { + // re-parent control window + // this is necessary if the control is running in a "low integrity" process that isn't + // permitted to create a child window with hostWnd as parent + int winStyle = GetWindowLongPtr(controlWnd, GWL_STYLE); + winStyle &= ~WS_CAPTION; // remove title bar + winStyle |= WS_CHILD; // convert to child window + SetWindowLongPtr(controlWnd, GWL_STYLE, winStyle); + SetParent(controlWnd, hostWnd); + } + if (!m_spOleControl) m_spOleObject->QueryInterface(IID_IOleControl, reinterpret_cast<void **>(&m_spOleControl)); if (m_spOleControl) { diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index d11fbeb..4d277b6 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -1644,12 +1644,25 @@ HWND QAxServerBase::create(HWND hWndParent, RECT& rcPos) } Q_ASSERT(!m_hWnd); + // will fail if parent window belongs to a higher integrity level process HWND hWnd = ::CreateWindow(reinterpret_cast<const wchar_t *>(cn.utf16()), 0, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, rcPos.left, rcPos.top, rcPos.right - rcPos.left, rcPos.bottom - rcPos.top, hWndParent, 0, hInst, this); // m_hWnd is assigned in reponse to WM_CREATE if (!hWnd) { + DWORD err = GetLastError(); + if (err == ERROR_ACCESS_DENIED) { + // retry without parent window + // the window will now need to be re-parented in the container process + hWnd = ::CreateWindow(reinterpret_cast<const wchar_t *>(cn.utf16()), 0, + WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + rcPos.left, rcPos.top, rcPos.right - rcPos.left, + rcPos.bottom - rcPos.top, nullptr, 0, hInst, this); + } + } + + if (!hWnd) { qErrnoWarning("%s: CreateWindow() failed", __FUNCTION__); return nullptr; } |