1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #ifndef QFUNCTIONS_WINRT_H
41 #define QFUNCTIONS_WINRT_H
42
43 #include <QtCore/qglobal.h>
44
45 #ifdef Q_OS_WIN
46
47 #include <QtCore/QCoreApplication>
48 #include <QtCore/QThread>
49 #include <QtCore/QAbstractEventDispatcher>
50 #include <QtCore/QElapsedTimer>
51 #include <QtCore/qt_windows.h>
52
53 // Convenience macros for handling HRESULT values
54 #define RETURN_IF_FAILED(msg, ret) \
55 if (FAILED(hr)) { \
56 qErrnoWarning(hr, msg); \
57 ret; \
58 }
59
60 #define RETURN_IF_FAILED_WITH_ARGS(msg, ret, ...) \
61 if (FAILED(hr)) { \
62 qErrnoWarning(hr, msg, __VA_ARGS__); \
63 ret; \
64 }
65
66 #define RETURN_HR_IF_FAILED(msg) RETURN_IF_FAILED(msg, return hr)
67 #define RETURN_OK_IF_FAILED(msg) RETURN_IF_FAILED(msg, return S_OK)
68 #define RETURN_FALSE_IF_FAILED(msg) RETURN_IF_FAILED(msg, return false)
69 #define RETURN_VOID_IF_FAILED(msg) RETURN_IF_FAILED(msg, return)
70 #define RETURN_HR_IF_FAILED_WITH_ARGS(msg, ...) RETURN_IF_FAILED_WITH_ARGS(msg, return hr, __VA_ARGS__)
71 #define RETURN_OK_IF_FAILED_WITH_ARGS(msg, ...) RETURN_IF_FAILED_WITH_ARGS(msg, return S_OK, __VA_ARGS__)
72 #define RETURN_FALSE_IF_FAILED_WITH_ARGS(msg, ...) RETURN_IF_FAILED_WITH_ARGS(msg, return false, __VA_ARGS__)
73 #define RETURN_VOID_IF_FAILED_WITH_ARGS(msg, ...) RETURN_IF_FAILED_WITH_ARGS(msg, return, __VA_ARGS__)
74
75 #define Q_ASSERT_SUCCEEDED(hr) \
76 Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr)));
77
78 #ifdef Q_OS_WINRT
79
80 QT_BEGIN_NAMESPACE
81
82 #ifdef QT_BUILD_CORE_LIB
83 #endif
84
85 // Environment ------------------------------------------------------
86 errno_t qt_fake_getenv_s(size_t*, char*, size_t, const char*);
87 errno_t qt_fake__putenv_s(const char*, const char*);
88 void qt_winrt_tzset();
89 void qt_winrt__tzset();
90
91 QT_END_NAMESPACE
92
93 // As Windows Runtime lacks some standard functions used in Qt, these got
94 // reimplemented. Other projects do this as well. Inline functions are used
95 // that there is a central place to disable functions for newer versions if
96 // they get available. There are no defines used anymore, because this
97 // will break member functions of classes which are called like these
98 // functions.
99 // The other declarations available in this file are being used per
100 // define inside qplatformdefs.h of the corresponding WinRT mkspec.
101
102 #define generate_inline_return_func0(funcname, returntype) \
103 inline returntype funcname() \
104 { \
105 return QT_PREPEND_NAMESPACE(qt_winrt_##funcname)(); \
106 }
107 #define generate_inline_return_func1(funcname, returntype, param1) \
108 inline returntype funcname(param1 p1) \
109 { \
110 return QT_PREPEND_NAMESPACE(qt_winrt_##funcname)(p1); \
111 }
112 #define generate_inline_return_func2(funcname, returntype, prependnamespace, param1, param2) \
113 inline returntype funcname(param1 p1, param2 p2) \
114 { \
115 return QT_PREPEND_NAMESPACE(prependnamespace##funcname)(p1, p2); \
116 }
117 #define generate_inline_return_func3(funcname, returntype, param1, param2, param3) \
118 inline returntype funcname(param1 p1, param2 p2, param3 p3) \
119 { \
120 return QT_PREPEND_NAMESPACE(qt_winrt_##funcname)(p1, p2, p3); \
121 }
122 #define generate_inline_return_func4(funcname, returntype, prependnamespace, param1, param2, param3, param4) \
123 inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4) \
124 { \
125 return QT_PREPEND_NAMESPACE(prependnamespace##funcname)(p1, p2, p3, p4); \
126 }
127 #define generate_inline_return_func5(funcname, returntype, param1, param2, param3, param4, param5) \
128 inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5) \
129 { \
130 return QT_PREPEND_NAMESPACE(qt_winrt_##funcname)(p1, p2, p3, p4, p5); \
131 }
132 #define generate_inline_return_func6(funcname, returntype, param1, param2, param3, param4, param5, param6) \
133 inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6) \
134 { \
135 return QT_PREPEND_NAMESPACE(qt_winrt_##funcname)(p1, p2, p3, p4, p5, p6); \
136 }
137 #define generate_inline_return_func7(funcname, returntype, param1, param2, param3, param4, param5, param6, param7) \
138 inline returntype funcname(param1 p1, param2 p2, param3 p3, param4 p4, param5 p5, param6 p6, param7 p7) \
139 { \
140 return QT_PREPEND_NAMESPACE(qt_winrt_##funcname)(p1, p2, p3, p4, p5, p6, p7); \
141 }
142
143 typedef unsigned (__stdcall *StartAdressExFunc)(void *);
144 typedef void(*StartAdressFunc)(void *);
145 typedef int ( __cdecl *CompareFunc ) (const void *, const void *) ;
146
generate_inline_return_func4(getenv_s,errno_t,qt_fake_,size_t *,char *,size_t,const char *)147 generate_inline_return_func4(getenv_s, errno_t, qt_fake_, size_t *, char *, size_t, const char *)
148 generate_inline_return_func2(_putenv_s, errno_t, qt_fake_, const char *, const char *)
149 generate_inline_return_func0(tzset, void)
150 generate_inline_return_func0(_tzset, void)
151
152 namespace Microsoft {
153 namespace WRL {
154 template <typename T> class ComPtr;
155 }
156 }
157
158 QT_BEGIN_NAMESPACE
159
160 namespace QWinRTFunctions {
161
162 // Synchronization methods
163 enum AwaitStyle
164 {
165 YieldThread = 0,
166 ProcessThreadEvents = 1,
167 ProcessMainThreadEvents = 2
168 };
169
170 template <typename T>
_await_impl(const Microsoft::WRL::ComPtr<T> & asyncOp,AwaitStyle awaitStyle,uint timeout)171 static inline HRESULT _await_impl(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle, uint timeout)
172 {
173 Microsoft::WRL::ComPtr<IAsyncInfo> asyncInfo;
174 HRESULT hr = asyncOp.As(&asyncInfo);
175 if (FAILED(hr))
176 return hr;
177
178 AsyncStatus status;
179 QElapsedTimer t;
180 if (timeout)
181 t.start();
182 switch (awaitStyle) {
183 case ProcessMainThreadEvents:
184 while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
185 QCoreApplication::processEvents();
186 if (timeout && t.hasExpired(timeout))
187 return ERROR_TIMEOUT;
188 }
189 break;
190 case ProcessThreadEvents:
191 if (QAbstractEventDispatcher *dispatcher = QThread::currentThread()->eventDispatcher()) {
192 while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
193 dispatcher->processEvents(QEventLoop::AllEvents);
194 if (timeout && t.hasExpired(timeout))
195 return ERROR_TIMEOUT;
196 }
197 break;
198 }
199 // fall through
200 default:
201 case YieldThread:
202 while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started) {
203 QThread::yieldCurrentThread();
204 if (timeout && t.hasExpired(timeout))
205 return ERROR_TIMEOUT;
206 }
207 break;
208 }
209
210 if (FAILED(hr) || status != AsyncStatus::Completed) {
211 HRESULT ec;
212 hr = asyncInfo->get_ErrorCode(&ec);
213 if (FAILED(hr))
214 return hr;
215 hr = asyncInfo->Close();
216 if (FAILED(hr))
217 return hr;
218 return ec;
219 }
220
221 return hr;
222 }
223
224 template <typename T>
225 static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, AwaitStyle awaitStyle = YieldThread, uint timeout = 0)
226 {
227 HRESULT hr = _await_impl(asyncOp, awaitStyle, timeout);
228 if (FAILED(hr))
229 return hr;
230
231 return asyncOp->GetResults();
232 }
233
234 template <typename T, typename U>
235 static inline HRESULT await(const Microsoft::WRL::ComPtr<T> &asyncOp, U *results, AwaitStyle awaitStyle = YieldThread, uint timeout = 0)
236 {
237 HRESULT hr = _await_impl(asyncOp, awaitStyle, timeout);
238 if (FAILED(hr))
239 return hr;
240
241 return asyncOp->GetResults(results);
242 }
243
244 } // QWinRTFunctions
245
246 QT_END_NAMESPACE
247
248 #endif // Q_OS_WINRT
249
250 #endif // Q_OS_WIN
251
252 #endif // QFUNCTIONS_WINRT_H
253