summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Wolff <oliver.wolff@qt.io>2017-02-02 10:58:19 +0100
committerOliver Wolff <oliver.wolff@qt.io>2017-02-08 11:03:25 +0000
commit65e0bfc0a78f5ebcf58d77f735d80e70bf4ba812 (patch)
treeb75ea46c36a6df62b0e052d618278b5dd0132784
parent7bde4b5dbd0381cf2f79158074625e9dea52b67e (diff)
winrt: Accept malformed profile descriptor list from applications
Other backends accept a malformed profile descriptor list which only contains a short uuid. WinRt seems to be more restrictive here and expects a nested sequence containing a short uuid and a version per entry. In order not to break existing applications the WinRT backend repairs the profile descriptor list's structure so that it is accepted as part of IRfcommServiceProvider's list of sdp attributes. Task-number: QTBUG-58529 Change-Id: Ic1754135bc139a732ac014728ef9341205a59e86 Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_winrt.cpp72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
index 77376dd9..d72056b7 100644
--- a/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
+++ b/src/bluetooth/qbluetoothserviceinfo_winrt.cpp
@@ -74,6 +74,69 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT)
extern QHash<QBluetoothServerPrivate *, int> __fakeServerPorts;
+bool repairProfileDescriptorListIfNeeded(ComPtr<IBuffer> &buffer)
+{
+ ComPtr<IDataReaderStatics> dataReaderStatics;
+ HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(),
+ &dataReaderStatics);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IDataReader> reader;
+ hr = dataReaderStatics->FromBuffer(buffer.Get(), reader.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ BYTE type;
+ hr = reader->ReadByte(&type);
+ Q_ASSERT_SUCCEEDED(hr);
+ if (type != TYPE_SEQUENCE) {
+ qCWarning(QT_BT_WINRT) << Q_FUNC_INFO << "Malformed profile descriptor list read";
+ return false;
+ }
+
+ quint8 length;
+ hr = reader->ReadByte(&length);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = reader->ReadByte(&type);
+ Q_ASSERT_SUCCEEDED(hr);
+ // We have to "repair" the structure if the outer sequence contains a uuid directly
+ if (type == TYPE_SHORT_UUID && length == 4) {
+ qCDebug(QT_BT_WINRT) << Q_FUNC_INFO << "Repairing profile descriptor list";
+ quint16 uuid;
+ hr = reader->ReadUInt16(&uuid);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IDataWriter> writer;
+ hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataWriter).Get(),
+ &writer);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = writer->WriteByte(TYPE_SEQUENCE);
+ Q_ASSERT_SUCCEEDED(hr);
+ // 8 == length of nested sequence (outer sequence -> inner sequence -> uuid and version)
+ hr = writer->WriteByte(8);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = writer->WriteByte(TYPE_SEQUENCE);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = writer->WriteByte(7);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = writer->WriteByte(TYPE_SHORT_UUID);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = writer->WriteUInt16(uuid);
+ Q_ASSERT_SUCCEEDED(hr);
+ // Write default version to make WinRT happy
+ hr = writer->WriteByte(TYPE_UINT16);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = writer->WriteUInt16(0x100);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = writer->DetachBuffer(&buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ return true;
+}
+
static ComPtr<IBuffer> bufferFromAttribute(const QVariant &attribute)
{
ComPtr<IDataWriter> writer;
@@ -361,6 +424,15 @@ bool QBluetoothServiceInfoPrivate::writeSdpAttributes()
return false;
}
+ // Other backends support a wrong structure in profile descriptor list. In order to make
+ // WinRT accept the list without breaking existing apps we have to repair this structure.
+ if (key == QBluetoothServiceInfo::BluetoothProfileDescriptorList) {
+ if (!repairProfileDescriptorListIfNeeded(buffer)) {
+ qCWarning(QT_BT_WINRT) << Q_FUNC_INFO << "Error while checking/repairing structure of profile descriptor list";
+ return false;
+ }
+ }
+
hr = writer->WriteBuffer(buffer.Get());
Q_ASSERT_SUCCEEDED(hr);