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