summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJøger Hansegård <joger.hansegard@qt.io>2023-06-11 16:14:28 +0200
committerJøger Hansegård <joger.hansegard@qt.io>2023-08-15 06:49:11 +0000
commitc92c897a700492878b767af7e10074e236b39f92 (patch)
tree741acaaf0b52b26d09ff75847fa7149836130714 /src
parent58a3cfe8574550872d47d7e08ae9b62e3b99bfd1 (diff)
Fix issues that caused ActiveQt qutlook sample to crash
The issues reported on qutlook sample appears to be caused by previous hardening of the QVariant type, which now does not accept copying uncopyable types. The fix to this problem seems to be to be more consistent on use of pointer types (which are copyable), vs value types generated by the dumpcpp preprocessor. In the function VARIANTToQVariant, we may end up in constructing a wrapper object on top of an IDispatch interface. To be able to construct an object, we need the value type of the wrapper object. Still, we should pass it out as a pointer type. This change ensures that a pointer type is returned if a pointer type was requested. A second similar issue is fixed in QAxBase::internalInvoke, by passing (what I assume is) the destination type into VARIANTToQVariant. This prevents decaying pointer types into value types. I am not sure if this is the right approach here, and it leaves the decay code behind, which now might be unused. Task-number: QTBUG-111191 Pick-to: 6.5 6.6 Change-Id: I0331ee5e3f2dbeed2db45e152378c223feb6fc94 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/activeqt/container/qaxbase.cpp2
-rw-r--r--src/activeqt/shared/qaxtypes.cpp36
2 files changed, 30 insertions, 8 deletions
diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp
index 973347b..5ba59c3 100644
--- a/src/activeqt/container/qaxbase.cpp
+++ b/src/activeqt/container/qaxbase.cpp
@@ -3452,7 +3452,7 @@ int QAxBase::internalInvoke(QMetaObject::Call call, int index, void **v)
// get return value
if (hres == S_OK && ret.vt != VT_EMPTY) {
- QVariantToVoidStar(VARIANTToQVariant(ret, slot.typeName()), v[0], slot.typeName());
+ QVariantToVoidStar(VARIANTToQVariant(ret, slot.typeName(), slot.returnType()), v[0], slot.typeName());
if (ret.vt != VT_DISPATCH)
clearVARIANT(&ret);
else
diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp
index 027511c..0dfbe28 100644
--- a/src/activeqt/shared/qaxtypes.cpp
+++ b/src/activeqt/shared/qaxtypes.cpp
@@ -718,7 +718,10 @@ static QVariant axServer(IUnknown *unknown, const QByteArray &typeName)
#undef QVARIANT_TO_VARIANT_POD
/*
- Returns \a arg as a QVariant of type \a type.
+ Returns \a arg as a QVariant of type \a typeName or \a type.
+
+ NOTE: If a \a typeName is specified, value type is assumed. to
+ get/create a pointer type, provide the type id in the \a type argument.
Used by
@@ -933,24 +936,43 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, int t
{
if (!typeName.isEmpty()) {
if (arg.vt & VT_BYREF) {
+ // When the dispinterface is a return value, just assign it to a QVariant
static const int dispatchId = qRegisterMetaType<IDispatch**>("IDispatch**");
var = QVariant(QMetaType(dispatchId), &arg.ppdispVal);
} else {
#ifndef QAX_SERVER
if (typeName == "QVariant") {
+ // If a QVariant is requested, wrap the dispinterface in a QAxObject
QAxObject *object = new QAxObject(disp);
var = QVariant::fromValue<QAxObject*>(object);
} else if (typeName != "IDispatch*" && QMetaType::fromName(typeName).id() != QMetaType::UnknownType) {
- QByteArray typeNameStr = QByteArray(typeName);
+ // Conversion from IDispatch* to a wrapper type is requested. Here, the requested
+ // wrapper type is constructed around the dispinterface, and then returned as
+ // a QVariant containing a pointer to the wrapper type.
+
+ // Calculate the value type from a potential pointer type
+ QByteArray valueTypeStr = QByteArray(typeName);
int pIndex = typeName.lastIndexOf('*');
if (pIndex != -1)
- typeNameStr = typeName.left(pIndex);
- const QMetaType metaType = QMetaType::fromName(typeNameStr);
- Q_ASSERT(metaType.id() != QMetaType::UnknownType);
- auto object = static_cast<QAxObject*>(qax_createObjectWrapper(metaType.id(), disp));
- var = QVariant(metaType, &object);
+ valueTypeStr = typeName.left(pIndex);
+
+ const QMetaType metaValueType = QMetaType::fromName(valueTypeStr);
+ Q_ASSERT(metaValueType.id() != QMetaType::UnknownType);
+
+ auto object = static_cast<QAxObject*>(qax_createObjectWrapper(metaValueType.id(), disp));
+
+ // Return object as the original type
+ const QMetaType returnType = QMetaType::fromName(typeName);
+ Q_ASSERT(metaValueType.id() != QMetaType::UnknownType);
+
+ var = QVariant(returnType, &object);
+
+ // The result must be a pointer to an instance derived from QObject
+ Q_ASSERT((var.metaType().flags() & QMetaType::PointerToQObject) != 0);
} else {
#endif
+ // An IDispatch pointer is requested, no conversion required, just return as QVariant
+ // containing the pointer.
static const int dispatchId = qRegisterMetaType<IDispatch*>(typeName.constData());
var = QVariant(QMetaType(dispatchId), &disp);
#ifndef QAX_SERVER