From 89ba182737c05e13331904379e84ac550ce11063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8ger=20Hanseg=C3=A5rd?= Date: Thu, 27 Jun 2024 10:51:11 +0200 Subject: [PATCH] Use Microsoft::WRL::ComPtr to manage lifetime of QWindowsUiaMainProvider Using smart pointers for managing COM object lifetimes reduces risk of introducing reference counting regressions. Task-number: QTBUG-126530 Change-Id: If487b78eae6403c762205ecc042e8872e3a6b940 Reviewed-by: Oliver Wolff (cherry picked from commit f51896b74e57459748313af750c013353d013821) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/CMakeLists.txt | 1 + src/corelib/platform/windows/qcomptr_p.h | 43 +++++++++ .../uiautomation/qwindowsuiaaccessibility.cpp | 5 +- .../qwindowsuiagriditemprovider.cpp | 2 +- .../uiautomation/qwindowsuiagridprovider.cpp | 5 +- .../uiautomation/qwindowsuiamainprovider.cpp | 90 +++++++++---------- .../uiautomation/qwindowsuiamainprovider.h | 3 +- .../uiautomation/qwindowsuiaprovidercache.cpp | 9 +- .../uiautomation/qwindowsuiaprovidercache.h | 3 +- .../qwindowsuiaselectionitemprovider.cpp | 4 +- .../qwindowsuiaselectionprovider.cpp | 18 ++-- .../qwindowsuiatableitemprovider.cpp | 12 +-- .../uiautomation/qwindowsuiatableprovider.cpp | 12 +-- .../qwindowsuiatextrangeprovider.cpp | 2 +- .../windows/qcomobject/tst_qcomobject.cpp | 17 +--- 15 files changed, 126 insertions(+), 100 deletions(-) create mode 100644 src/corelib/platform/windows/qcomptr_p.h diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index fd460922447..43e0b39218a 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -561,6 +561,7 @@ qt_internal_extend_target(Core CONDITION WIN32 plugin/qsystemlibrary.cpp plugin/qsystemlibrary_p.h thread/qthread_win.cpp platform/windows/qcomobject_p.h + platform/windows/qcomptr_p.h LIBRARIES advapi32 authz diff --git a/src/corelib/platform/windows/qcomptr_p.h b/src/corelib/platform/windows/qcomptr_p.h new file mode 100644 index 00000000000..7ee286d254e --- /dev/null +++ b/src/corelib/platform/windows/qcomptr_p.h @@ -0,0 +1,43 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QCOMPTR_P_H +#define QCOMPTR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#if defined(Q_OS_WIN) || defined(Q_QDOC) + +#include +#include + +QT_BEGIN_NAMESPACE + +using Microsoft::WRL::ComPtr; + +template +ComPtr makeComObject(Args &&...args) +{ + ComPtr p; + // Don't use Attach because of MINGW64 bug + // #892 Microsoft::WRL::ComPtr::Attach leaks references + *p.GetAddressOf() = new T(std::forward(args)...); + return p; +} + +QT_END_NAMESPACE + +#endif // Q_OS_WIN + +#endif // QCOMPTR_P_H diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp index 3385959cc4e..638d684ce4f 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp @@ -46,9 +46,8 @@ bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARA if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) { if (QAccessibleInterface *accessible = window->accessibleRoot()) { - QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible); - *lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider); - provider->Release(); + auto provider = QWindowsUiaMainProvider::providerForAccessible(accessible); + *lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider.Get()); return true; } } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp index 8832c015d55..d919e50af4e 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.cpp @@ -129,7 +129,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ContainingGrid(IRawEl return UIA_E_ELEMENTNOTAVAILABLE; if (QAccessibleInterface *table = tableCellInterface->table()) { - *pRetVal = QWindowsUiaMainProvider::providerForAccessible(table); // Detach + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(table).Detach(); } return S_OK; } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp index 755b672143b..00e40488f6c 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.cpp @@ -45,9 +45,8 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::GetItem(int row, int column, return UIA_E_ELEMENTNOTAVAILABLE; if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) { - if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) { - *pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell); // Detach - } + if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell).Detach(); } return S_OK; } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 051af8b629f..3d4a03f7e9a 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -40,18 +40,18 @@ QT_BEGIN_NAMESPACE using namespace QWindowsUiAutomation; // Returns a cached instance of the provider for a specific accessible interface. -QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible) +ComPtr QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible) { if (!accessible) return nullptr; QAccessible::Id id = QAccessible::uniqueId(accessible); QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance(); - QWindowsUiaMainProvider *provider = providerCache->providerForId(id); + ComPtr provider = providerCache->providerForId(id); if (!provider) { - provider = new QWindowsUiaMainProvider(accessible); - providerCache->insert(id, provider); + provider = makeComObject(accessible); + providerCache->insert(id, provider.Get()); // Cache holds weak references } return provider; } @@ -73,10 +73,8 @@ void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event) if (QAccessibleInterface *child = accessible->focusChild()) accessible = child; } - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { - UiaRaiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId); - provider->Release(); - } + if (auto provider = providerForAccessible(accessible)) + UiaRaiseAutomationEvent(provider.Get(), UIA_AutomationFocusChangedEventId); } } @@ -86,34 +84,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve if (event->changedStates().checked || event->changedStates().checkStateMixed) { // Notifies states changes in checkboxes. if (accessible->role() == QAccessible::CheckBox) { - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (auto provider = providerForAccessible(accessible)) { VARIANT oldVal, newVal; clearVariant(&oldVal); int toggleState = ToggleState_Off; if (accessible->state().checked) toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On; setVariantI4(toggleState, &newVal); - UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ToggleToggleStatePropertyId, oldVal, newVal); - provider->Release(); + UiaRaiseAutomationPropertyChangedEvent( + provider.Get(), UIA_ToggleToggleStatePropertyId, oldVal, newVal); } } } if (event->changedStates().active) { if (accessible->role() == QAccessible::Window) { // Notifies window opened/closed. - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (auto provider = providerForAccessible(accessible)) { if (accessible->state().active) { - UiaRaiseAutomationEvent(provider, UIA_Window_WindowOpenedEventId); + UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowOpenedEventId); if (QAccessibleInterface *focused = accessible->focusChild()) { - if (QWindowsUiaMainProvider *focusedProvider = providerForAccessible(focused)) { - UiaRaiseAutomationEvent(focusedProvider, UIA_AutomationFocusChangedEventId); - focusedProvider->Release(); + if (auto focusedProvider = providerForAccessible(focused)) { + UiaRaiseAutomationEvent(focusedProvider.Get(), + UIA_AutomationFocusChangedEventId); } } } else { - UiaRaiseAutomationEvent(provider, UIA_Window_WindowClosedEventId); + UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowClosedEventId); } - provider->Release(); } } } @@ -140,26 +137,26 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve } } if (event->value().typeId() == QMetaType::QString) { - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (auto provider = providerForAccessible(accessible)) { // Notifies changes in string values. VARIANT oldVal, newVal; clearVariant(&oldVal); setVariantString(event->value().toString(), &newVal); - UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal); - provider->Release(); + UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_ValueValuePropertyId, + oldVal, newVal); HRESULT hr = VariantClear(&newVal); // Free string allocated by setVariantString Q_ASSERT(hr == S_OK); Q_UNUSED(hr) } } else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (auto provider = providerForAccessible(accessible)) { // Notifies changes in values of controls supporting the value interface. VARIANT oldVal, newVal; clearVariant(&oldVal); setVariantDouble(valueInterface->currentValue().toDouble(), &newVal); - UiaRaiseAutomationPropertyChangedEvent(provider, UIA_RangeValueValuePropertyId, oldVal, newVal); - provider->Release(); + UiaRaiseAutomationPropertyChangedEvent( + provider.Get(), UIA_RangeValueValuePropertyId, oldVal, newVal); } } } @@ -171,13 +168,13 @@ void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event) // Restrict notification to combo boxes, which need it for accessibility, // in order to avoid slowdowns with unnecessary notifications. if (accessible->role() == QAccessible::ComboBox) { - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (auto provider = providerForAccessible(accessible)) { VARIANT oldVal, newVal; clearVariant(&oldVal); setVariantString(accessible->text(QAccessible::Name), &newVal); - UiaRaiseAutomationPropertyChangedEvent(provider, UIA_NamePropertyId, oldVal, newVal); + UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_NamePropertyId, oldVal, + newVal); ::SysFreeString(newVal.bstrVal); - provider->Release(); } } } @@ -186,10 +183,8 @@ void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event) void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event) { if (QAccessibleInterface *accessible = event->accessibleInterface()) { - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { - UiaRaiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId); - provider->Release(); - } + if (auto provider = providerForAccessible(accessible)) + UiaRaiseAutomationEvent(provider.Get(), UIA_SelectionItem_ElementSelectedEventId); } } @@ -198,17 +193,17 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event) { if (QAccessibleInterface *accessible = event->accessibleInterface()) { if (accessible->textInterface()) { - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (auto provider = providerForAccessible(accessible)) { if (event->type() == QAccessible::TextSelectionChanged) { - UiaRaiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId); + UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextSelectionChangedEventId); } else if (event->type() == QAccessible::TextCaretMoved) { if (!accessible->state().readOnly) { - UiaRaiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId); + UiaRaiseAutomationEvent(provider.Get(), + UIA_Text_TextSelectionChangedEventId); } } else { - UiaRaiseAutomationEvent(provider, UIA_Text_TextChangedEventId); + UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextChangedEventId); } - provider->Release(); } } } @@ -217,18 +212,18 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event) void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *event) { if (QAccessibleInterface *accessible = event->accessibleInterface()) { - if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + if (auto provider = providerForAccessible(accessible)) { BSTR message = bStrFromQString(event->message()); QAccessible::AnnouncementPoliteness prio = event->politeness(); NotificationProcessing processing = (prio == QAccessible::AnnouncementPoliteness::Assertive) ? NotificationProcessing_ImportantAll : NotificationProcessing_All; BSTR activityId = bStrFromQString(QString::fromLatin1("")); - UiaRaiseNotificationEvent(provider, NotificationKind_Other, processing, message, activityId); + UiaRaiseNotificationEvent(provider.Get(), NotificationKind_Other, processing, message, + activityId); ::SysFreeString(message); ::SysFreeString(activityId); - provider->Release(); } } } @@ -383,9 +378,9 @@ void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface* SAFEARRAY *elements = SafeArrayCreateVector(VT_UNKNOWN, 0, relationInterfaces.size()); for (LONG i = 0; i < relationInterfaces.size(); ++i) { - if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(relationInterfaces.at(i).first)) { - SafeArrayPutElement(elements, &i, static_cast(childProvider)); - childProvider->Release(); + if (ComPtr provider = + providerForAccessible(relationInterfaces.at(i).first)) { + SafeArrayPutElement(elements, &i, provider.Get()); } } @@ -697,7 +692,7 @@ HRESULT QWindowsUiaMainProvider::Navigate(NavigateDirection direction, IRawEleme } if (targetacc) - *pRetVal = providerForAccessible(targetacc); // Detach + *pRetVal = providerForAccessible(targetacc).Detach(); return S_OK; } @@ -785,9 +780,8 @@ HRESULT QWindowsUiaMainProvider::get_FragmentRoot(IRawElementProviderFragmentRoo // non-native controls/fragments. if (QAccessibleInterface *accessible = accessibleInterface()) { if (QWindow *window = windowForAccessible(accessible)) { - if (QAccessibleInterface *rootacc = window->accessibleRoot()) { - *pRetVal = providerForAccessible(rootacc); // Detach - } + if (QAccessibleInterface *rootacc = window->accessibleRoot()) + *pRetVal = providerForAccessible(rootacc).Detach(); } } return S_OK; @@ -827,7 +821,7 @@ HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IR if (targetacc->textInterface()) break; acc = acc->childAt(point.x(), point.y()); } - *pRetVal = providerForAccessible(targetacc); // Detach + *pRetVal = providerForAccessible(targetacc).Detach(); } return S_OK; } @@ -843,7 +837,7 @@ HRESULT QWindowsUiaMainProvider::GetFocus(IRawElementProviderFragment **pRetVal) if (QAccessibleInterface *accessible = accessibleInterface()) { if (QAccessibleInterface *focusacc = accessible->focusChild()) { - *pRetVal = providerForAccessible(focusacc); // Detach + *pRetVal = providerForAccessible(focusacc).Detach(); } } return S_OK; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h index f9cf22a2dab..03954d28050 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h @@ -14,6 +14,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -25,7 +26,7 @@ class QWindowsUiaMainProvider : Q_OBJECT Q_DISABLE_COPY_MOVE(QWindowsUiaMainProvider) public: - static QWindowsUiaMainProvider *providerForAccessible(QAccessibleInterface *accessible); + static ComPtr providerForAccessible(QAccessibleInterface *accessible); explicit QWindowsUiaMainProvider(QAccessibleInterface *a); virtual ~QWindowsUiaMainProvider(); static void notifyFocusChange(QAccessibleEvent *event); diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp index 9f8f5a93ebf..7aa095ee48a 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.cpp @@ -26,12 +26,13 @@ QWindowsUiaProviderCache *QWindowsUiaProviderCache::instance() } // Returns the provider instance associated with the ID, or nullptr. -QWindowsUiaMainProvider *QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const +ComPtr QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const { QMutexLocker guard{ &m_tableMutex }; - QWindowsUiaMainProvider *provider = m_providerTable.value(id); - if (provider) - provider->AddRef(); // Make sure lifetime is extended while holding the mutex + + // Make sure lifetime is extended while holding the mutex + ComPtr provider = m_providerTable.value(id); + return provider; } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h index 0351587f22b..5c3354c4a43 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaprovidercache.h @@ -12,6 +12,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -22,7 +23,7 @@ class QWindowsUiaProviderCache : public QObject Q_OBJECT public: static QWindowsUiaProviderCache *instance(); - QWindowsUiaMainProvider *providerForId(QAccessible::Id id) const; + ComPtr providerForId(QAccessible::Id id) const; void insert(QAccessible::Id id, QWindowsUiaMainProvider *provider); private Q_SLOTS: diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp index a7fc55d5a76..18cd14a2c95 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.cpp @@ -178,7 +178,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain QAccessibleInterface *parent = accessible->parent(); if (parent && parent->selectionInterface()) { - *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); // Detach + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent).Detach(); return S_OK; } @@ -190,7 +190,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain if (parent) { if ((accessible->role() == QAccessible::ListItem && parent->role() == QAccessible::List) || (accessible->role() == QAccessible::PageTab && parent->role() == QAccessible::PageTabList)) { - *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); // Detach + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent).Detach(); } } return S_OK; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp index 7e9d0151e25..1e176b66797 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.cpp @@ -65,9 +65,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY * if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selectedList.size()))) { for (LONG i = 0; i < selectedList.size(); ++i) { - if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) { - SafeArrayPutElement(*pRetVal, &i, static_cast(childProvider)); - childProvider->Release(); + if (ComPtr provider = + QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) { + SafeArrayPutElement(*pRetVal, &i, provider.Get()); } } } @@ -161,9 +161,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_FirstSelectedItem(__ if (!firstSelectedChild) return UIA_E_ELEMENTNOTAVAILABLE; - if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild)) - { - *pRetVal = static_cast(childProvider); // Detach + if (ComPtr childProvider = + QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild)) { + *pRetVal = childProvider.Detach(); return S_OK; } @@ -206,9 +206,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_LastSelectedItem(__R if (!lastSelectedChild) return UIA_E_ELEMENTNOTAVAILABLE; - if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild)) - { - *pRetVal = static_cast(childProvider); // Detach + if (ComPtr childProvider = + QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild)) { + *pRetVal = childProvider.Detach(); return S_OK; } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp index f92c4b3af79..070c5382eab 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.cpp @@ -48,9 +48,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetRowHeaderItems(SAFEAR if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { for (LONG i = 0; i < headers.size(); ++i) { - if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { - SafeArrayPutElement(*pRetVal, &i, static_cast(headerProvider)); - headerProvider->Release(); + if (ComPtr provider = + QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { + SafeArrayPutElement(*pRetVal, &i, provider.Get()); } } } @@ -78,9 +78,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetColumnHeaderItems(SAF if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { for (LONG i = 0; i < headers.size(); ++i) { - if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { - SafeArrayPutElement(*pRetVal, &i, static_cast(headerProvider)); - headerProvider->Release(); + if (ComPtr provider = + QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { + SafeArrayPutElement(*pRetVal, &i, provider.Get()); } } } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp index 9c7ede882d7..f3b1591e3ad 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.cpp @@ -55,9 +55,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetRowHeaders(SAFEARRAY **pR } if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { for (LONG i = 0; i < headers.size(); ++i) { - if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { - SafeArrayPutElement(*pRetVal, &i, static_cast(headerProvider)); - headerProvider->Release(); + if (ComPtr provider = + QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { + SafeArrayPutElement(*pRetVal, &i, provider.Get()); } } } @@ -92,9 +92,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetColumnHeaders(SAFEARRAY * } if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { for (LONG i = 0; i < headers.size(); ++i) { - if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { - SafeArrayPutElement(*pRetVal, &i, static_cast(headerProvider)); - headerProvider->Release(); + if (ComPtr provider = + QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { + SafeArrayPutElement(*pRetVal, &i, provider.Get()); } } } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp index 716c2e8e15a..d837aac811c 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp @@ -265,7 +265,7 @@ HRESULT QWindowsUiaTextRangeProvider::GetEnclosingElement(IRawElementProviderSim if (!accessible) return UIA_E_ELEMENTNOTAVAILABLE; - *pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible); // Detach + *pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible).Detach(); return S_OK; } diff --git a/tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp b/tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp index 3c609238fce..903ba208dfb 100644 --- a/tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp +++ b/tests/auto/corelib/platform/windows/qcomobject/tst_qcomobject.cpp @@ -5,24 +5,11 @@ #ifdef Q_OS_WIN -# include - -# include - -using Microsoft::WRL::ComPtr; +#include +#include QT_BEGIN_NAMESPACE -template -ComPtr makeComObject(Args &&...args) -{ - ComPtr p; - // Don't use Attach because of MINGW64 bug - // #892 Microsoft::WRL::ComPtr::Attach leaks references - *p.GetAddressOf() = new T(std::forward(args)...); - return p; -} - MIDL_INTERFACE("878fab04-7da0-41ea-9c49-058c7fa0d80a") IIntermediate : public IUnknown{};