diff options
author | Oliver Wolff <oliver.wolff@qt.io> | 2017-02-02 10:58:19 +0100 |
---|---|---|
committer | Oliver Wolff <oliver.wolff@qt.io> | 2017-02-08 11:03:25 +0000 |
commit | 65e0bfc0a78f5ebcf58d77f735d80e70bf4ba812 (patch) | |
tree | b75ea46c36a6df62b0e052d618278b5dd0132784 | |
parent | 7bde4b5dbd0381cf2f79158074625e9dea52b67e (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.cpp | 72 |
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); |