Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qbluetoothutils_winrt.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include <QtBluetooth/private/qtbluetoothglobal_p.h>
6#include <QtCore/private/qfunctions_winrt_p.h>
7#include <QtCore/QLoggingCategory>
8
9#include <robuffer.h>
10#include <wrl.h>
11#include <winrt/windows.foundation.metadata.h>
12#include <windows.storage.streams.h>
13
14using namespace Microsoft::WRL;
15using namespace Microsoft::WRL::Wrappers;
16using namespace winrt::Windows::Foundation::Metadata;
17using namespace ABI::Windows::Storage::Streams;
18
19QT_BEGIN_NAMESPACE
20
21Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS)
22
23QByteArray byteArrayFromBuffer(const ComPtr<NativeBuffer> &buffer, bool isWCharString)
24{
25 if (!buffer) {
26 qErrnoWarning("nullptr passed to byteArrayFromBuffer");
27 return QByteArray();
28 }
29 ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
30 HRESULT hr = buffer.As(&byteAccess);
31 RETURN_IF_FAILED("Could not cast buffer", return QByteArray())
32 char *data;
33 hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data));
34 RETURN_IF_FAILED("Could not obtain buffer data", return QByteArray())
35 UINT32 size;
36 hr = buffer->get_Length(&size);
37 RETURN_IF_FAILED("Could not obtain buffer size", return QByteArray())
38 if (isWCharString) {
39 QString valueString = QString::fromUtf16(reinterpret_cast<char16_t *>(data)).left(size / 2);
40 return valueString.toUtf8();
41 }
42 return QByteArray(data, qint32(size));
43}
44
45static QSet<void*> successfulInits;
46static QThread *mainThread = nullptr;
47
48void mainThreadCoInit(void* caller)
49{
50 Q_ASSERT(caller);
51
52 if (QThread::currentThread() != QCoreApplication::instance()->thread()) {
53 qCWarning(QT_BT_WINDOWS) << "Main thread COM init tried from another thread";
54 return;
55 }
56
57 if (successfulInits.contains(caller)) {
58 qCWarning(QT_BT_WINDOWS) << "Multiple COM inits by same object";
59 return;
60 }
61
62 Q_ASSERT_X(!mainThread || mainThread == QThread::currentThread(),
63 __FUNCTION__, "QCoreApplication's thread has changed!");
64
65 // This executes in main thread which may run Gui => use apartment threaded
66 if (!SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) {
67 qCWarning(QT_BT_WINDOWS) << "Unexpected COM initialization result";
68 return;
69 }
70 successfulInits.insert(caller);
71 if (!mainThread)
72 mainThread = QThread::currentThread();
73}
74
75void mainThreadCoUninit(void* caller)
76{
77 Q_ASSERT(caller);
78
79 if (!successfulInits.contains(caller)) {
80 qCWarning(QT_BT_WINDOWS) << "COM uninitialization without initialization";
81 return;
82 }
83
84 if (QThread::currentThread() != mainThread) {
85 qCWarning(QT_BT_WINDOWS) << "Main thread COM uninit tried from another thread";
86 return;
87 }
88
89 CoUninitialize();
90 successfulInits.remove(caller);
91
92}
93
94QT_END_NAMESPACE
static QThread * mainThread
void mainThreadCoInit(void *caller)
void mainThreadCoUninit(void *caller)