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 <oliver.wolff@qt.io>
(cherry picked from commit f51896b74e57459748313af750c013353d013821)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Jøger Hansegård 2024-06-27 10:51:11 +02:00 committed by Qt Cherry-pick Bot
parent 29c32e7cdc
commit 89ba182737
15 changed files with 126 additions and 100 deletions

View File

@ -561,6 +561,7 @@ qt_internal_extend_target(Core CONDITION WIN32
plugin/qsystemlibrary.cpp plugin/qsystemlibrary_p.h plugin/qsystemlibrary.cpp plugin/qsystemlibrary_p.h
thread/qthread_win.cpp thread/qthread_win.cpp
platform/windows/qcomobject_p.h platform/windows/qcomobject_p.h
platform/windows/qcomptr_p.h
LIBRARIES LIBRARIES
advapi32 advapi32
authz authz

View File

@ -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 <QtCore/private/qglobal_p.h>
#if defined(Q_OS_WIN) || defined(Q_QDOC)
#include <QtCore/qt_windows.h>
#include <wrl/client.h>
QT_BEGIN_NAMESPACE
using Microsoft::WRL::ComPtr;
template <typename T, typename... Args>
ComPtr<T> makeComObject(Args &&...args)
{
ComPtr<T> p;
// Don't use Attach because of MINGW64 bug
// #892 Microsoft::WRL::ComPtr::Attach leaks references
*p.GetAddressOf() = new T(std::forward<Args>(args)...);
return p;
}
QT_END_NAMESPACE
#endif // Q_OS_WIN
#endif // QCOMPTR_P_H

View File

@ -46,9 +46,8 @@ bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARA
if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) { if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
if (QAccessibleInterface *accessible = window->accessibleRoot()) { if (QAccessibleInterface *accessible = window->accessibleRoot()) {
QWindowsUiaMainProvider *provider = QWindowsUiaMainProvider::providerForAccessible(accessible); auto provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
*lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider); *lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider.Get());
provider->Release();
return true; return true;
} }
} }

View File

@ -129,7 +129,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridItemProvider::get_ContainingGrid(IRawEl
return UIA_E_ELEMENTNOTAVAILABLE; return UIA_E_ELEMENTNOTAVAILABLE;
if (QAccessibleInterface *table = tableCellInterface->table()) { if (QAccessibleInterface *table = tableCellInterface->table()) {
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(table); // Detach *pRetVal = QWindowsUiaMainProvider::providerForAccessible(table).Detach();
} }
return S_OK; return S_OK;
} }

View File

@ -45,9 +45,8 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaGridProvider::GetItem(int row, int column,
return UIA_E_ELEMENTNOTAVAILABLE; return UIA_E_ELEMENTNOTAVAILABLE;
if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) { if ((row >= 0) && (row < tableInterface->rowCount()) && (column >= 0) && (column < tableInterface->columnCount())) {
if (QAccessibleInterface *cell = tableInterface->cellAt(row, column)) { if (QAccessibleInterface *cell = tableInterface->cellAt(row, column))
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell); // Detach *pRetVal = QWindowsUiaMainProvider::providerForAccessible(cell).Detach();
}
} }
return S_OK; return S_OK;
} }

View File

@ -40,18 +40,18 @@ QT_BEGIN_NAMESPACE
using namespace QWindowsUiAutomation; using namespace QWindowsUiAutomation;
// Returns a cached instance of the provider for a specific accessible interface. // Returns a cached instance of the provider for a specific accessible interface.
QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible) ComPtr<QWindowsUiaMainProvider> QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible)
{ {
if (!accessible) if (!accessible)
return nullptr; return nullptr;
QAccessible::Id id = QAccessible::uniqueId(accessible); QAccessible::Id id = QAccessible::uniqueId(accessible);
QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance(); QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance();
QWindowsUiaMainProvider *provider = providerCache->providerForId(id); ComPtr<QWindowsUiaMainProvider> provider = providerCache->providerForId(id);
if (!provider) { if (!provider) {
provider = new QWindowsUiaMainProvider(accessible); provider = makeComObject<QWindowsUiaMainProvider>(accessible);
providerCache->insert(id, provider); providerCache->insert(id, provider.Get()); // Cache holds weak references
} }
return provider; return provider;
} }
@ -73,10 +73,8 @@ void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
if (QAccessibleInterface *child = accessible->focusChild()) if (QAccessibleInterface *child = accessible->focusChild())
accessible = child; accessible = child;
} }
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (auto provider = providerForAccessible(accessible))
UiaRaiseAutomationEvent(provider, UIA_AutomationFocusChangedEventId); UiaRaiseAutomationEvent(provider.Get(), UIA_AutomationFocusChangedEventId);
provider->Release();
}
} }
} }
@ -86,34 +84,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
if (event->changedStates().checked || event->changedStates().checkStateMixed) { if (event->changedStates().checked || event->changedStates().checkStateMixed) {
// Notifies states changes in checkboxes. // Notifies states changes in checkboxes.
if (accessible->role() == QAccessible::CheckBox) { if (accessible->role() == QAccessible::CheckBox) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (auto provider = providerForAccessible(accessible)) {
VARIANT oldVal, newVal; VARIANT oldVal, newVal;
clearVariant(&oldVal); clearVariant(&oldVal);
int toggleState = ToggleState_Off; int toggleState = ToggleState_Off;
if (accessible->state().checked) if (accessible->state().checked)
toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On; toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
setVariantI4(toggleState, &newVal); setVariantI4(toggleState, &newVal);
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ToggleToggleStatePropertyId, oldVal, newVal); UiaRaiseAutomationPropertyChangedEvent(
provider->Release(); provider.Get(), UIA_ToggleToggleStatePropertyId, oldVal, newVal);
} }
} }
} }
if (event->changedStates().active) { if (event->changedStates().active) {
if (accessible->role() == QAccessible::Window) { if (accessible->role() == QAccessible::Window) {
// Notifies window opened/closed. // Notifies window opened/closed.
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (auto provider = providerForAccessible(accessible)) {
if (accessible->state().active) { if (accessible->state().active) {
UiaRaiseAutomationEvent(provider, UIA_Window_WindowOpenedEventId); UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowOpenedEventId);
if (QAccessibleInterface *focused = accessible->focusChild()) { if (QAccessibleInterface *focused = accessible->focusChild()) {
if (QWindowsUiaMainProvider *focusedProvider = providerForAccessible(focused)) { if (auto focusedProvider = providerForAccessible(focused)) {
UiaRaiseAutomationEvent(focusedProvider, UIA_AutomationFocusChangedEventId); UiaRaiseAutomationEvent(focusedProvider.Get(),
focusedProvider->Release(); UIA_AutomationFocusChangedEventId);
} }
} }
} else { } 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 (event->value().typeId() == QMetaType::QString) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (auto provider = providerForAccessible(accessible)) {
// Notifies changes in string values. // Notifies changes in string values.
VARIANT oldVal, newVal; VARIANT oldVal, newVal;
clearVariant(&oldVal); clearVariant(&oldVal);
setVariantString(event->value().toString(), &newVal); setVariantString(event->value().toString(), &newVal);
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal); UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_ValueValuePropertyId,
provider->Release(); oldVal, newVal);
HRESULT hr = VariantClear(&newVal); // Free string allocated by setVariantString HRESULT hr = VariantClear(&newVal); // Free string allocated by setVariantString
Q_ASSERT(hr == S_OK); Q_ASSERT(hr == S_OK);
Q_UNUSED(hr) Q_UNUSED(hr)
} }
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { } 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. // Notifies changes in values of controls supporting the value interface.
VARIANT oldVal, newVal; VARIANT oldVal, newVal;
clearVariant(&oldVal); clearVariant(&oldVal);
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal); setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_RangeValueValuePropertyId, oldVal, newVal); UiaRaiseAutomationPropertyChangedEvent(
provider->Release(); 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, // Restrict notification to combo boxes, which need it for accessibility,
// in order to avoid slowdowns with unnecessary notifications. // in order to avoid slowdowns with unnecessary notifications.
if (accessible->role() == QAccessible::ComboBox) { if (accessible->role() == QAccessible::ComboBox) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (auto provider = providerForAccessible(accessible)) {
VARIANT oldVal, newVal; VARIANT oldVal, newVal;
clearVariant(&oldVal); clearVariant(&oldVal);
setVariantString(accessible->text(QAccessible::Name), &newVal); setVariantString(accessible->text(QAccessible::Name), &newVal);
UiaRaiseAutomationPropertyChangedEvent(provider, UIA_NamePropertyId, oldVal, newVal); UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_NamePropertyId, oldVal,
newVal);
::SysFreeString(newVal.bstrVal); ::SysFreeString(newVal.bstrVal);
provider->Release();
} }
} }
} }
@ -186,10 +183,8 @@ void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event) void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
{ {
if (QAccessibleInterface *accessible = event->accessibleInterface()) { if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (auto provider = providerForAccessible(accessible))
UiaRaiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId); UiaRaiseAutomationEvent(provider.Get(), UIA_SelectionItem_ElementSelectedEventId);
provider->Release();
}
} }
} }
@ -198,17 +193,17 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
{ {
if (QAccessibleInterface *accessible = event->accessibleInterface()) { if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (accessible->textInterface()) { if (accessible->textInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (auto provider = providerForAccessible(accessible)) {
if (event->type() == QAccessible::TextSelectionChanged) { if (event->type() == QAccessible::TextSelectionChanged) {
UiaRaiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId); UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextSelectionChangedEventId);
} else if (event->type() == QAccessible::TextCaretMoved) { } else if (event->type() == QAccessible::TextCaretMoved) {
if (!accessible->state().readOnly) { if (!accessible->state().readOnly) {
UiaRaiseAutomationEvent(provider, UIA_Text_TextSelectionChangedEventId); UiaRaiseAutomationEvent(provider.Get(),
UIA_Text_TextSelectionChangedEventId);
} }
} else { } 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) void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *event)
{ {
if (QAccessibleInterface *accessible = event->accessibleInterface()) { if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (auto provider = providerForAccessible(accessible)) {
BSTR message = bStrFromQString(event->message()); BSTR message = bStrFromQString(event->message());
QAccessible::AnnouncementPoliteness prio = event->politeness(); QAccessible::AnnouncementPoliteness prio = event->politeness();
NotificationProcessing processing = (prio == QAccessible::AnnouncementPoliteness::Assertive) NotificationProcessing processing = (prio == QAccessible::AnnouncementPoliteness::Assertive)
? NotificationProcessing_ImportantAll ? NotificationProcessing_ImportantAll
: NotificationProcessing_All; : NotificationProcessing_All;
BSTR activityId = bStrFromQString(QString::fromLatin1("")); BSTR activityId = bStrFromQString(QString::fromLatin1(""));
UiaRaiseNotificationEvent(provider, NotificationKind_Other, processing, message, activityId); UiaRaiseNotificationEvent(provider.Get(), NotificationKind_Other, processing, message,
activityId);
::SysFreeString(message); ::SysFreeString(message);
::SysFreeString(activityId); ::SysFreeString(activityId);
provider->Release();
} }
} }
} }
@ -383,9 +378,9 @@ void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface*
SAFEARRAY *elements = SafeArrayCreateVector(VT_UNKNOWN, 0, relationInterfaces.size()); SAFEARRAY *elements = SafeArrayCreateVector(VT_UNKNOWN, 0, relationInterfaces.size());
for (LONG i = 0; i < relationInterfaces.size(); ++i) { for (LONG i = 0; i < relationInterfaces.size(); ++i) {
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(relationInterfaces.at(i).first)) { if (ComPtr<IRawElementProviderSimple> provider =
SafeArrayPutElement(elements, &i, static_cast<IRawElementProviderSimple*>(childProvider)); providerForAccessible(relationInterfaces.at(i).first)) {
childProvider->Release(); SafeArrayPutElement(elements, &i, provider.Get());
} }
} }
@ -697,7 +692,7 @@ HRESULT QWindowsUiaMainProvider::Navigate(NavigateDirection direction, IRawEleme
} }
if (targetacc) if (targetacc)
*pRetVal = providerForAccessible(targetacc); // Detach *pRetVal = providerForAccessible(targetacc).Detach();
return S_OK; return S_OK;
} }
@ -785,9 +780,8 @@ HRESULT QWindowsUiaMainProvider::get_FragmentRoot(IRawElementProviderFragmentRoo
// non-native controls/fragments. // non-native controls/fragments.
if (QAccessibleInterface *accessible = accessibleInterface()) { if (QAccessibleInterface *accessible = accessibleInterface()) {
if (QWindow *window = windowForAccessible(accessible)) { if (QWindow *window = windowForAccessible(accessible)) {
if (QAccessibleInterface *rootacc = window->accessibleRoot()) { if (QAccessibleInterface *rootacc = window->accessibleRoot())
*pRetVal = providerForAccessible(rootacc); // Detach *pRetVal = providerForAccessible(rootacc).Detach();
}
} }
} }
return S_OK; return S_OK;
@ -827,7 +821,7 @@ HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(double x, double y, IR
if (targetacc->textInterface()) break; if (targetacc->textInterface()) break;
acc = acc->childAt(point.x(), point.y()); acc = acc->childAt(point.x(), point.y());
} }
*pRetVal = providerForAccessible(targetacc); // Detach *pRetVal = providerForAccessible(targetacc).Detach();
} }
return S_OK; return S_OK;
} }
@ -843,7 +837,7 @@ HRESULT QWindowsUiaMainProvider::GetFocus(IRawElementProviderFragment **pRetVal)
if (QAccessibleInterface *accessible = accessibleInterface()) { if (QAccessibleInterface *accessible = accessibleInterface()) {
if (QAccessibleInterface *focusacc = accessible->focusChild()) { if (QAccessibleInterface *focusacc = accessible->focusChild()) {
*pRetVal = providerForAccessible(focusacc); // Detach *pRetVal = providerForAccessible(focusacc).Detach();
} }
} }
return S_OK; return S_OK;

View File

@ -14,6 +14,7 @@
#include <QtCore/qmutex.h> #include <QtCore/qmutex.h>
#include <QtCore/qt_windows.h> #include <QtCore/qt_windows.h>
#include <QtGui/qaccessible.h> #include <QtGui/qaccessible.h>
#include <QtCore/private/qcomptr_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -25,7 +26,7 @@ class QWindowsUiaMainProvider :
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY_MOVE(QWindowsUiaMainProvider) Q_DISABLE_COPY_MOVE(QWindowsUiaMainProvider)
public: public:
static QWindowsUiaMainProvider *providerForAccessible(QAccessibleInterface *accessible); static ComPtr<QWindowsUiaMainProvider> providerForAccessible(QAccessibleInterface *accessible);
explicit QWindowsUiaMainProvider(QAccessibleInterface *a); explicit QWindowsUiaMainProvider(QAccessibleInterface *a);
virtual ~QWindowsUiaMainProvider(); virtual ~QWindowsUiaMainProvider();
static void notifyFocusChange(QAccessibleEvent *event); static void notifyFocusChange(QAccessibleEvent *event);

View File

@ -26,12 +26,13 @@ QWindowsUiaProviderCache *QWindowsUiaProviderCache::instance()
} }
// Returns the provider instance associated with the ID, or nullptr. // Returns the provider instance associated with the ID, or nullptr.
QWindowsUiaMainProvider *QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const ComPtr<QWindowsUiaMainProvider> QWindowsUiaProviderCache::providerForId(QAccessible::Id id) const
{ {
QMutexLocker guard{ &m_tableMutex }; QMutexLocker guard{ &m_tableMutex };
QWindowsUiaMainProvider *provider = m_providerTable.value(id);
if (provider) // Make sure lifetime is extended while holding the mutex
provider->AddRef(); // Make sure lifetime is extended while holding the mutex ComPtr<QWindowsUiaMainProvider> provider = m_providerTable.value(id);
return provider; return provider;
} }

View File

@ -12,6 +12,7 @@
#include <QtCore/qhash.h> #include <QtCore/qhash.h>
#include <QtCore/qmutex.h> #include <QtCore/qmutex.h>
#include <QtGui/qaccessible.h> #include <QtGui/qaccessible.h>
#include <QtCore/private/qcomptr_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -22,7 +23,7 @@ class QWindowsUiaProviderCache : public QObject
Q_OBJECT Q_OBJECT
public: public:
static QWindowsUiaProviderCache *instance(); static QWindowsUiaProviderCache *instance();
QWindowsUiaMainProvider *providerForId(QAccessible::Id id) const; ComPtr<QWindowsUiaMainProvider> providerForId(QAccessible::Id id) const;
void insert(QAccessible::Id id, QWindowsUiaMainProvider *provider); void insert(QAccessible::Id id, QWindowsUiaMainProvider *provider);
private Q_SLOTS: private Q_SLOTS:

View File

@ -178,7 +178,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
QAccessibleInterface *parent = accessible->parent(); QAccessibleInterface *parent = accessible->parent();
if (parent && parent->selectionInterface()) { if (parent && parent->selectionInterface()) {
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); // Detach *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent).Detach();
return S_OK; return S_OK;
} }
@ -190,7 +190,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionItemProvider::get_SelectionContain
if (parent) { if (parent) {
if ((accessible->role() == QAccessible::ListItem && parent->role() == QAccessible::List) if ((accessible->role() == QAccessible::ListItem && parent->role() == QAccessible::List)
|| (accessible->role() == QAccessible::PageTab && parent->role() == QAccessible::PageTabList)) { || (accessible->role() == QAccessible::PageTab && parent->role() == QAccessible::PageTabList)) {
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent); // Detach *pRetVal = QWindowsUiaMainProvider::providerForAccessible(parent).Detach();
} }
} }
return S_OK; return S_OK;

View File

@ -65,9 +65,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY *
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selectedList.size()))) { if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selectedList.size()))) {
for (LONG i = 0; i < selectedList.size(); ++i) { for (LONG i = 0; i < selectedList.size(); ++i) {
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) { if (ComPtr<IRawElementProviderSimple> provider =
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(childProvider)); QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) {
childProvider->Release(); SafeArrayPutElement(*pRetVal, &i, provider.Get());
} }
} }
} }
@ -161,9 +161,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_FirstSelectedItem(__
if (!firstSelectedChild) if (!firstSelectedChild)
return UIA_E_ELEMENTNOTAVAILABLE; return UIA_E_ELEMENTNOTAVAILABLE;
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild)) if (ComPtr<IRawElementProviderSimple> childProvider =
{ QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild)) {
*pRetVal = static_cast<IRawElementProviderSimple *>(childProvider); // Detach *pRetVal = childProvider.Detach();
return S_OK; return S_OK;
} }
@ -206,9 +206,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_LastSelectedItem(__R
if (!lastSelectedChild) if (!lastSelectedChild)
return UIA_E_ELEMENTNOTAVAILABLE; return UIA_E_ELEMENTNOTAVAILABLE;
if (QWindowsUiaMainProvider *childProvider = QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild)) if (ComPtr<IRawElementProviderSimple> childProvider =
{ QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild)) {
*pRetVal = static_cast<IRawElementProviderSimple *>(childProvider); // Detach *pRetVal = childProvider.Detach();
return S_OK; return S_OK;
} }

View File

@ -48,9 +48,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetRowHeaderItems(SAFEAR
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
for (LONG i = 0; i < headers.size(); ++i) { for (LONG i = 0; i < headers.size(); ++i) {
if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { if (ComPtr<IRawElementProviderSimple> provider =
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider)); QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
headerProvider->Release(); SafeArrayPutElement(*pRetVal, &i, provider.Get());
} }
} }
} }
@ -78,9 +78,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableItemProvider::GetColumnHeaderItems(SAF
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
for (LONG i = 0; i < headers.size(); ++i) { for (LONG i = 0; i < headers.size(); ++i) {
if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { if (ComPtr<IRawElementProviderSimple> provider =
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider)); QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
headerProvider->Release(); SafeArrayPutElement(*pRetVal, &i, provider.Get());
} }
} }
} }

View File

@ -55,9 +55,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetRowHeaders(SAFEARRAY **pR
} }
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
for (LONG i = 0; i < headers.size(); ++i) { for (LONG i = 0; i < headers.size(); ++i) {
if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { if (ComPtr<IRawElementProviderSimple> provider =
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider)); QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
headerProvider->Release(); SafeArrayPutElement(*pRetVal, &i, provider.Get());
} }
} }
} }
@ -92,9 +92,9 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTableProvider::GetColumnHeaders(SAFEARRAY *
} }
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) { if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, headers.size()))) {
for (LONG i = 0; i < headers.size(); ++i) { for (LONG i = 0; i < headers.size(); ++i) {
if (QWindowsUiaMainProvider *headerProvider = QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) { if (ComPtr<IRawElementProviderSimple> provider =
SafeArrayPutElement(*pRetVal, &i, static_cast<IRawElementProviderSimple *>(headerProvider)); QWindowsUiaMainProvider::providerForAccessible(headers.at(i))) {
headerProvider->Release(); SafeArrayPutElement(*pRetVal, &i, provider.Get());
} }
} }
} }

View File

@ -265,7 +265,7 @@ HRESULT QWindowsUiaTextRangeProvider::GetEnclosingElement(IRawElementProviderSim
if (!accessible) if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE; return UIA_E_ELEMENTNOTAVAILABLE;
*pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible); // Detach *pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible).Detach();
return S_OK; return S_OK;
} }

View File

@ -6,23 +6,10 @@
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <private/qcomobject_p.h> #include <private/qcomobject_p.h>
#include <QtCore/private/qcomptr_p.h>
# include <wrl/client.h>
using Microsoft::WRL::ComPtr;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
template <typename T, typename... Args>
ComPtr<T> makeComObject(Args &&...args)
{
ComPtr<T> p;
// Don't use Attach because of MINGW64 bug
// #892 Microsoft::WRL::ComPtr::Attach leaks references
*p.GetAddressOf() = new T(std::forward<Args>(args)...);
return p;
}
MIDL_INTERFACE("878fab04-7da0-41ea-9c49-058c7fa0d80a") MIDL_INTERFACE("878fab04-7da0-41ea-9c49-058c7fa0d80a")
IIntermediate : public IUnknown{}; IIntermediate : public IUnknown{};