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
qcoreapplication_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
2// Copyright (C) 2016 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
7#include "qstringlist.h"
8#include "qdir.h"
9#include "qfileinfo.h"
10#ifndef QT_NO_QOBJECT
11#include "qmutex.h"
12#include <private/qthread_p.h>
13#include <private/qlocking_p.h>
14#endif
15#include "qtextstream.h"
17#include <ctype.h>
18#include <qt_windows.h>
19
21
22using namespace Qt::StringLiterals;
23
24// By default, we get the path to the host .exe. ActiveQt can override this
25// with the component's DLL.
26Q_CONSTINIT void *QCoreApplicationPrivate::mainInstanceHandle = nullptr;
27QString qAppFileName() // get application file name
28{
29 /*
30 GetModuleFileName() returns the length of the module name, when it has
31 space to store it and 0-terminate; this return is necessarily smaller than
32 the buffer size, as it doesn't include the terminator. When it lacks
33 space, the function returns the full size of the buffer and fills the
34 buffer, truncating the full path to make it fit. We have reports that
35 GetModuleFileName sometimes doesn't set the error number to
36 ERROR_INSUFFICIENT_BUFFER, as claimed by the MSDN documentation; so we
37 only trust the answer when the return is actually less than the buffer
38 size we pass in. (When truncating, except on XP, it does so by enough to
39 still have space to 0-terminate; in either case, it fills the claimed
40 space and returns the size of the space. While XP might thus give us the
41 full name, without a 0 terminator, and return its actual length, we can
42 never be sure that's what's happened until a later call with bigger buffer
43 confirms it by returning less than its buffer size.)
44 */
45 // Full path may be longer than MAX_PATH - expand until we have enough space:
46 QVarLengthArray<wchar_t, MAX_PATH + 1> space;
47 DWORD v;
48 size_t size = 1;
49 do {
50 size += MAX_PATH;
51 space.resize(int(size));
52 auto hInstance = reinterpret_cast<HINSTANCE>(QCoreApplicationPrivate::mainInstanceHandle);
53 v = GetModuleFileName(hInstance, space.data(), DWORD(space.size()));
54 } while (Q_UNLIKELY(v >= size));
55
56 // QCoreApplication::applicationFilePath() expects a canonical path with
57 // Qt-style separators
58 QStringView nativePath(space.data(), v);
59 return QDir::fromNativeSeparators(nativePath.toString());
60}
61
62QString QCoreApplicationPrivate::appName() const
63{
64 return QFileInfo(qAppFileName()).baseName();
65}
66
67QString QCoreApplicationPrivate::appVersion() const
68{
69 QString applicationVersion;
70#ifndef QT_BOOTSTRAPPED
71 const QString appFileName = qAppFileName();
72 QVarLengthArray<wchar_t> buffer(appFileName.size() + 1);
73 buffer[appFileName.toWCharArray(buffer.data())] = 0;
74
75 DWORD versionInfoSize = GetFileVersionInfoSize(buffer.data(), nullptr);
76 if (versionInfoSize) {
77 QVarLengthArray<BYTE> info(static_cast<int>(versionInfoSize));
78 if (GetFileVersionInfo(buffer.data(), 0, versionInfoSize, info.data())) {
79 UINT size;
80 DWORD *fi;
81
82 if (VerQueryValue(info.data(), __TEXT("\\"),
83 reinterpret_cast<void **>(&fi), &size) && size) {
84 const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
85 applicationVersion = QStringLiteral("%1.%2.%3.%4")
86 .arg(HIWORD(verInfo->dwProductVersionMS))
87 .arg(LOWORD(verInfo->dwProductVersionMS))
88 .arg(HIWORD(verInfo->dwProductVersionLS))
89 .arg(LOWORD(verInfo->dwProductVersionLS));
90 }
91 }
92 }
93#endif
94 return applicationVersion;
95}
96
97#ifndef QT_NO_QOBJECT
98
99#if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG_STREAM)
100/*****************************************************************************
101 Convenience functions for convert WM_* messages into human readable strings,
102 including a nifty QDebug operator<< for simple QDebug() << msg output.
103 *****************************************************************************/
104QT_BEGIN_INCLUDE_NAMESPACE
105#include <windowsx.h>
106#include "qdebug.h"
107QT_END_INCLUDE_NAMESPACE
108
109#if !defined(GET_X_LPARAM)
110# define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
111# define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
112#endif
113
114// The values below should never change. Note that none of the usual
115// WM_...FIRST & WM_...LAST values are in the list, as they normally have other
116// WM_... representations
117
118template <class IntType>
119struct QWinMessageMapping {
120 IntType value;
121 const char *name;
122};
123
124#define FLAG_ENTRY(x) {x, #x} // for populating arrays
125
126// Looks up a value in a list of QWinMessageMapping
127template <class IntType>
128static const char *findWinMessageMapping(const QWinMessageMapping<IntType> *haystack,
129 size_t haystackSize,
130 IntType needle)
131{
132 for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
133 if (p->value == needle)
134 return p->name;
135 }
136 return nullptr;
137}
138
139// Format flags using a mapping as "Flag1 | Flag2"...
140template <class IntType>
141static QString flagsValue(const QWinMessageMapping<IntType> *haystack,
142 size_t haystackSize, IntType value)
143{
144 QString result;
145 for (auto p = haystack, end = haystack + haystackSize; p < end; ++p) {
146 if ((p->value & value) == p->value) {
147 if (!result.isEmpty())
148 result += " | "_L1;
149 result += QLatin1StringView(p->name);
150 }
151 }
152 return result;
153}
154
155// Looks up the WM_ message in the table inside
156static const char *findWMstr(uint msg)
157{
158 static const QWinMessageMapping<uint> knownWM[] =
159{{ 0x0000, "WM_NULL" },
160 { 0x0001, "WM_CREATE" },
161 { 0x0002, "WM_DESTROY" },
162 { 0x0003, "WM_MOVE" },
163 { 0x0005, "WM_SIZE" },
164 { 0x0006, "WM_ACTIVATE" },
165 { 0x0007, "WM_SETFOCUS" },
166 { 0x0008, "WM_KILLFOCUS" },
167 { 0x000A, "WM_ENABLE" },
168 { 0x000B, "WM_SETREDRAW" },
169 { 0x000C, "WM_SETTEXT" },
170 { 0x000D, "WM_GETTEXT" },
171 { 0x000E, "WM_GETTEXTLENGTH" },
172 { 0x000F, "WM_PAINT" },
173 { 0x0010, "WM_CLOSE" },
174 { 0x0011, "WM_QUERYENDSESSION" },
175 { 0x0013, "WM_QUERYOPEN" },
176 { 0x0016, "WM_ENDSESSION" },
177 { 0x0012, "WM_QUIT" },
178 { 0x0014, "WM_ERASEBKGND" },
179 { 0x0015, "WM_SYSCOLORCHANGE" },
180 { 0x0018, "WM_SHOWWINDOW" },
181 { 0x001A, "WM_SETTINGCHANGE" },
182 { 0x001B, "WM_DEVMODECHANGE" },
183 { 0x001C, "WM_ACTIVATEAPP" },
184 { 0x001D, "WM_FONTCHANGE" },
185 { 0x001E, "WM_TIMECHANGE" },
186 { 0x001F, "WM_CANCELMODE" },
187 { 0x0020, "WM_SETCURSOR" },
188 { 0x0021, "WM_MOUSEACTIVATE" },
189 { 0x0022, "WM_CHILDACTIVATE" },
190 { 0x0023, "WM_QUEUESYNC" },
191 { 0x0024, "WM_GETMINMAXINFO" },
192 { 0x0026, "WM_PAINTICON" },
193 { 0x0027, "WM_ICONERASEBKGND" },
194 { 0x0028, "WM_NEXTDLGCTL" },
195 { 0x002A, "WM_SPOOLERSTATUS" },
196 { 0x002B, "WM_DRAWITEM" },
197 { 0x002C, "WM_MEASUREITEM" },
198 { 0x002D, "WM_DELETEITEM" },
199 { 0x002E, "WM_VKEYTOITEM" },
200 { 0x002F, "WM_CHARTOITEM" },
201 { 0x0030, "WM_SETFONT" },
202 { 0x0031, "WM_GETFONT" },
203 { 0x0032, "WM_SETHOTKEY" },
204 { 0x0033, "WM_GETHOTKEY" },
205 { 0x0037, "WM_QUERYDRAGICON" },
206 { 0x0039, "WM_COMPAREITEM" },
207 { 0x003D, "WM_GETOBJECT" },
208 { 0x0041, "WM_COMPACTING" },
209 { 0x0044, "WM_COMMNOTIFY" },
210 { 0x0046, "WM_WINDOWPOSCHANGING" },
211 { 0x0047, "WM_WINDOWPOSCHANGED" },
212 { 0x0048, "WM_POWER" },
213 { 0x004A, "WM_COPYDATA" },
214 { 0x004B, "WM_CANCELJOURNAL" },
215 { 0x004E, "WM_NOTIFY" },
216 { 0x0050, "WM_INPUTLANGCHANGEREQUEST" },
217 { 0x0051, "WM_INPUTLANGCHANGE" },
218 { 0x0052, "WM_TCARD" },
219 { 0x0053, "WM_HELP" },
220 { 0x0054, "WM_USERCHANGED" },
221 { 0x0055, "WM_NOTIFYFORMAT" },
222 { 0x007B, "WM_CONTEXTMENU" },
223 { 0x007C, "WM_STYLECHANGING" },
224 { 0x007D, "WM_STYLECHANGED" },
225 { 0x007E, "WM_DISPLAYCHANGE" },
226 { 0x007F, "WM_GETICON" },
227 { 0x0080, "WM_SETICON" },
228 { 0x0081, "WM_NCCREATE" },
229 { 0x0082, "WM_NCDESTROY" },
230 { 0x0083, "WM_NCCALCSIZE" },
231 { 0x0084, "WM_NCHITTEST" },
232 { 0x0085, "WM_NCPAINT" },
233 { 0x0086, "WM_NCACTIVATE" },
234 { 0x0087, "WM_GETDLGCODE" },
235 { 0x0088, "WM_SYNCPAINT" },
236 { 0x00A0, "WM_NCMOUSEMOVE" },
237 { 0x00A1, "WM_NCLBUTTONDOWN" },
238 { 0x00A2, "WM_NCLBUTTONUP" },
239 { 0x00A3, "WM_NCLBUTTONDBLCLK" },
240 { 0x00A4, "WM_NCRBUTTONDOWN" },
241 { 0x00A5, "WM_NCRBUTTONUP" },
242 { 0x00A6, "WM_NCRBUTTONDBLCLK" },
243 { 0x00A7, "WM_NCMBUTTONDOWN" },
244 { 0x00A8, "WM_NCMBUTTONUP" },
245 { 0x00A9, "WM_NCMBUTTONDBLCLK" },
246 { 0x00AB, "WM_NCXBUTTONDOWN" },
247 { 0x00AC, "WM_NCXBUTTONUP" },
248 { 0x00AD, "WM_NCXBUTTONDBLCLK" },
249 { 0x00FF, "WM_INPUT" },
250 { 0x0100, "WM_KEYDOWN" },
251 { 0x0101, "WM_KEYUP" },
252 { 0x0102, "WM_CHAR" },
253 { 0x0103, "WM_DEADCHAR" },
254 { 0x0104, "WM_SYSKEYDOWN" },
255 { 0x0105, "WM_SYSKEYUP" },
256 { 0x0106, "WM_SYSCHAR" },
257 { 0x0107, "WM_SYSDEADCHAR" },
258 { 0x0109, "WM_UNICHAR" },
259 { 0x010D, "WM_IME_STARTCOMPOSITION" },
260 { 0x010E, "WM_IME_ENDCOMPOSITION" },
261 { 0x010F, "WM_IME_COMPOSITION" },
262 { 0x0110, "WM_INITDIALOG" },
263 { 0x0111, "WM_COMMAND" },
264 { 0x0112, "WM_SYSCOMMAND" },
265 { 0x0113, "WM_TIMER" },
266 { 0x0114, "WM_HSCROLL" },
267 { 0x0115, "WM_VSCROLL" },
268 { 0x0116, "WM_INITMENU" },
269 { 0x0117, "WM_INITMENUPOPUP" },
270 { 0x011F, "WM_MENUSELECT" },
271 { 0x0120, "WM_MENUCHAR" },
272 { 0x0121, "WM_ENTERIDLE" },
273 { 0x0122, "WM_MENURBUTTONUP" },
274 { 0x0123, "WM_MENUDRAG" },
275 { 0x0124, "WM_MENUGETOBJECT" },
276 { 0x0125, "WM_UNINITMENUPOPUP" },
277 { 0x0126, "WM_MENUCOMMAND" },
278 { 0x0127, "WM_CHANGEUISTATE" },
279 { 0x0128, "WM_UPDATEUISTATE" },
280 { 0x0129, "WM_QUERYUISTATE" },
281 { 0x0132, "WM_CTLCOLORMSGBOX" },
282 { 0x0133, "WM_CTLCOLOREDIT" },
283 { 0x0134, "WM_CTLCOLORLISTBOX" },
284 { 0x0135, "WM_CTLCOLORBTN" },
285 { 0x0136, "WM_CTLCOLORDLG" },
286 { 0x0137, "WM_CTLCOLORSCROLLBAR" },
287 { 0x0138, "WM_CTLCOLORSTATIC" },
288 { 0x0200, "WM_MOUSEMOVE" },
289 { 0x0201, "WM_LBUTTONDOWN" },
290 { 0x0202, "WM_LBUTTONUP" },
291 { 0x0203, "WM_LBUTTONDBLCLK" },
292 { 0x0204, "WM_RBUTTONDOWN" },
293 { 0x0205, "WM_RBUTTONUP" },
294 { 0x0206, "WM_RBUTTONDBLCLK" },
295 { 0x0207, "WM_MBUTTONDOWN" },
296 { 0x0208, "WM_MBUTTONUP" },
297 { 0x0209, "WM_MBUTTONDBLCLK" },
298 { 0x020A, "WM_MOUSEWHEEL" },
299 { 0x020B, "WM_XBUTTONDOWN" },
300 { 0x020C, "WM_XBUTTONUP" },
301 { 0x020D, "WM_XBUTTONDBLCLK" },
302 { 0x020E, "WM_MOUSEHWHEEL" },
303 { 0x0210, "WM_PARENTNOTIFY" },
304 { 0x0211, "WM_ENTERMENULOOP" },
305 { 0x0212, "WM_EXITMENULOOP" },
306 { 0x0213, "WM_NEXTMENU" },
307 { 0x0214, "WM_SIZING" },
308 { 0x0215, "WM_CAPTURECHANGED" },
309 { 0x0216, "WM_MOVING" },
310 { 0x0218, "WM_POWERBROADCAST" },
311 { 0x0219, "WM_DEVICECHANGE" },
312 { 0x0220, "WM_MDICREATE" },
313 { 0x0221, "WM_MDIDESTROY" },
314 { 0x0222, "WM_MDIACTIVATE" },
315 { 0x0223, "WM_MDIRESTORE" },
316 { 0x0224, "WM_MDINEXT" },
317 { 0x0225, "WM_MDIMAXIMIZE" },
318 { 0x0226, "WM_MDITILE" },
319 { 0x0227, "WM_MDICASCADE" },
320 { 0x0228, "WM_MDIICONARRANGE" },
321 { 0x0229, "WM_MDIGETACTIVE" },
322 { 0x0230, "WM_MDISETMENU" },
323 { 0x0231, "WM_ENTERSIZEMOVE" },
324 { 0x0232, "WM_EXITSIZEMOVE" },
325 { 0x0233, "WM_DROPFILES" },
326 { 0x0234, "WM_MDIREFRESHMENU" },
327 { 0x0241, "WM_NCPOINTERUPDATE"},
328 { 0x0242, "WM_NCPOINTERDOWN"},
329 { 0x0243, "WM_NCPOINTERUP"},
330 { 0x0245, "WM_POINTERUPDATE"},
331 { 0x0246, "WM_POINTERDOWN"},
332 { 0x0247, "WM_POINTERUP"},
333 { 0x0249, "WM_POINTERENTER"},
334 { 0x024A, "WM_POINTERLEAVE"},
335 { 0x0248, "WM_POINTERACTIVATE"},
336 { 0x024C, "WM_POINTERCAPTURECHANGED"},
337 { 0x024D, "WM_TOUCHHITTESTING"},
338 { 0x024E, "WM_POINTERWHEEL"},
339 { 0x024F, "WM_POINTERHWHEEL"},
340 { 0x0250, "DM_POINTERHITTEST"},
341 { 0x0251, "WM_POINTERROUTEDTO"},
342 { 0x0252, "WM_POINTERROUTEDAWAY"},
343 { 0x0253, "WM_POINTERROUTEDRELEASED"},
344 { 0x0281, "WM_IME_SETCONTEXT" },
345 { 0x0282, "WM_IME_NOTIFY" },
346 { 0x0283, "WM_IME_CONTROL" },
347 { 0x0284, "WM_IME_COMPOSITIONFULL" },
348 { 0x0285, "WM_IME_SELECT" },
349 { 0x0286, "WM_IME_CHAR" },
350 { 0x0288, "WM_IME_REQUEST" },
351 { 0x0290, "WM_IME_KEYDOWN" },
352 { 0x0291, "WM_IME_KEYUP" },
353 { 0x02A0, "WM_NCMOUSEHOVER" },
354 { 0x02A1, "WM_MOUSEHOVER" },
355 { 0x02A2, "WM_NCMOUSELEAVE" },
356 { 0x02A3, "WM_MOUSELEAVE" },
357 { 0x02B1, "WM_WTSSESSION_CHANGE" },
358 { 0x02C0, "WM_TABLET_FIRST" },
359 { 0x02C1, "WM_TABLET_FIRST + 1" },
360 { 0x02C2, "WM_TABLET_FIRST + 2" },
361 { 0x02C3, "WM_TABLET_FIRST + 3" },
362 { 0x02C4, "WM_TABLET_FIRST + 4" },
363 { 0x02C5, "WM_TABLET_FIRST + 5" },
364 { 0x02C6, "WM_TABLET_FIRST + 6" },
365 { 0x02C7, "WM_TABLET_FIRST + 7" },
366 { 0x02C8, "WM_TABLET_FIRST + 8" },
367 { 0x02C9, "WM_TABLET_FIRST + 9" },
368 { 0x02CA, "WM_TABLET_FIRST + 10" },
369 { 0x02CB, "WM_TABLET_FIRST + 11" },
370 { 0x02CC, "WM_TABLET_FIRST + 12" },
371 { 0x02CD, "WM_TABLET_FIRST + 13" },
372 { 0x02CE, "WM_TABLET_FIRST + 14" },
373 { 0x02CF, "WM_TABLET_FIRST + 15" },
374 { 0x02D0, "WM_TABLET_FIRST + 16" },
375 { 0x02D1, "WM_TABLET_FIRST + 17" },
376 { 0x02D2, "WM_TABLET_FIRST + 18" },
377 { 0x02D3, "WM_TABLET_FIRST + 19" },
378 { 0x02D4, "WM_TABLET_FIRST + 20" },
379 { 0x02D5, "WM_TABLET_FIRST + 21" },
380 { 0x02D6, "WM_TABLET_FIRST + 22" },
381 { 0x02D7, "WM_TABLET_FIRST + 23" },
382 { 0x02D8, "WM_TABLET_FIRST + 24" },
383 { 0x02D9, "WM_TABLET_FIRST + 25" },
384 { 0x02DA, "WM_TABLET_FIRST + 26" },
385 { 0x02DB, "WM_TABLET_FIRST + 27" },
386 { 0x02DC, "WM_TABLET_FIRST + 28" },
387 { 0x02DD, "WM_TABLET_FIRST + 29" },
388 { 0x02DE, "WM_TABLET_FIRST + 30" },
389 { 0x02DF, "WM_TABLET_LAST" },
390 { 0x02E0, "WM_DPICHANGED" },
391 { 0x0300, "WM_CUT" },
392 { 0x0301, "WM_COPY" },
393 { 0x0302, "WM_PASTE" },
394 { 0x0303, "WM_CLEAR" },
395 { 0x0304, "WM_UNDO" },
396 { 0x0305, "WM_RENDERFORMAT" },
397 { 0x0306, "WM_RENDERALLFORMATS" },
398 { 0x0307, "WM_DESTROYCLIPBOARD" },
399 { 0x0308, "WM_DRAWCLIPBOARD" },
400 { 0x0309, "WM_PAINTCLIPBOARD" },
401 { 0x030A, "WM_VSCROLLCLIPBOARD" },
402 { 0x030B, "WM_SIZECLIPBOARD" },
403 { 0x030C, "WM_ASKCBFORMATNAME" },
404 { 0x030D, "WM_CHANGECBCHAIN" },
405 { 0x030E, "WM_HSCROLLCLIPBOARD" },
406 { 0x030F, "WM_QUERYNEWPALETTE" },
407 { 0x0310, "WM_PALETTEISCHANGING" },
408 { 0x0311, "WM_PALETTECHANGED" },
409 { 0x0312, "WM_HOTKEY" },
410 { 0x0317, "WM_PRINT" },
411 { 0x0318, "WM_PRINTCLIENT" },
412 { 0x0319, "WM_APPCOMMAND" },
413 { 0x0320, "WM_DWMCOLORIZATIONCOLORCHANGED" },
414 { 0x031A, "WM_THEMECHANGED" },
415 { 0x0358, "WM_HANDHELDFIRST" },
416 { 0x0359, "WM_HANDHELDFIRST + 1" },
417 { 0x035A, "WM_HANDHELDFIRST + 2" },
418 { 0x035B, "WM_HANDHELDFIRST + 3" },
419 { 0x035C, "WM_HANDHELDFIRST + 4" },
420 { 0x035D, "WM_HANDHELDFIRST + 5" },
421 { 0x035E, "WM_HANDHELDFIRST + 6" },
422 { 0x035F, "WM_HANDHELDLAST" },
423 { 0x0360, "WM_AFXFIRST" },
424 { 0x0361, "WM_AFXFIRST + 1" },
425 { 0x0362, "WM_AFXFIRST + 2" },
426 { 0x0363, "WM_AFXFIRST + 3" },
427 { 0x0364, "WM_AFXFIRST + 4" },
428 { 0x0365, "WM_AFXFIRST + 5" },
429 { 0x0366, "WM_AFXFIRST + 6" },
430 { 0x0367, "WM_AFXFIRST + 7" },
431 { 0x0368, "WM_AFXFIRST + 8" },
432 { 0x0369, "WM_AFXFIRST + 9" },
433 { 0x036A, "WM_AFXFIRST + 10" },
434 { 0x036B, "WM_AFXFIRST + 11" },
435 { 0x036C, "WM_AFXFIRST + 12" },
436 { 0x036D, "WM_AFXFIRST + 13" },
437 { 0x036E, "WM_AFXFIRST + 14" },
438 { 0x036F, "WM_AFXFIRST + 15" },
439 { 0x0370, "WM_AFXFIRST + 16" },
440 { 0x0371, "WM_AFXFIRST + 17" },
441 { 0x0372, "WM_AFXFIRST + 18" },
442 { 0x0373, "WM_AFXFIRST + 19" },
443 { 0x0374, "WM_AFXFIRST + 20" },
444 { 0x0375, "WM_AFXFIRST + 21" },
445 { 0x0376, "WM_AFXFIRST + 22" },
446 { 0x0377, "WM_AFXFIRST + 23" },
447 { 0x0378, "WM_AFXFIRST + 24" },
448 { 0x0379, "WM_AFXFIRST + 25" },
449 { 0x037A, "WM_AFXFIRST + 26" },
450 { 0x037B, "WM_AFXFIRST + 27" },
451 { 0x037C, "WM_AFXFIRST + 28" },
452 { 0x037D, "WM_AFXFIRST + 29" },
453 { 0x037E, "WM_AFXFIRST + 30" },
454 { 0x037F, "WM_AFXLAST" },
455 { 0x0380, "WM_PENWINFIRST" },
456 { 0x0381, "WM_PENWINFIRST + 1" },
457 { 0x0382, "WM_PENWINFIRST + 2" },
458 { 0x0383, "WM_PENWINFIRST + 3" },
459 { 0x0384, "WM_PENWINFIRST + 4" },
460 { 0x0385, "WM_PENWINFIRST + 5" },
461 { 0x0386, "WM_PENWINFIRST + 6" },
462 { 0x0387, "WM_PENWINFIRST + 7" },
463 { 0x0388, "WM_PENWINFIRST + 8" },
464 { 0x0389, "WM_PENWINFIRST + 9" },
465 { 0x038A, "WM_PENWINFIRST + 10" },
466 { 0x038B, "WM_PENWINFIRST + 11" },
467 { 0x038C, "WM_PENWINFIRST + 12" },
468 { 0x038D, "WM_PENWINFIRST + 13" },
469 { 0x038E, "WM_PENWINFIRST + 14" },
470 { 0x038F, "WM_PENWINLAST" },
471 { 0x0400, "WM_USER" },
472 { 0x8000, "WM_APP" }
473 };
474
475 return findWinMessageMapping(knownWM, sizeof(knownWM) / sizeof(knownWM[0]), msg);
476}
477
478static const char *activateParameter(uint p)
479{
480 static const QWinMessageMapping<uint> activeEnum[] = {
481 {WA_ACTIVE, "Activate"}, {WA_INACTIVE, "Deactivate"},
482 {WA_CLICKACTIVE, "Activate by mouseclick"}
483 };
484
485 return findWinMessageMapping(activeEnum, sizeof(activeEnum) / sizeof(activeEnum[0]), p);
486}
487
488static QString styleFlags(uint style)
489{
490 static const QWinMessageMapping<uint> styleFlags[] = {
491 FLAG_ENTRY(WS_BORDER), FLAG_ENTRY(WS_CAPTION), FLAG_ENTRY(WS_CHILD),
492 FLAG_ENTRY(WS_CLIPCHILDREN), FLAG_ENTRY(WS_CLIPSIBLINGS),
493 FLAG_ENTRY(WS_DISABLED), FLAG_ENTRY(WS_DLGFRAME), FLAG_ENTRY(WS_GROUP),
494 FLAG_ENTRY(WS_HSCROLL), FLAG_ENTRY(WS_OVERLAPPED),
495 FLAG_ENTRY(WS_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_ICONIC),
496 FLAG_ENTRY(WS_MAXIMIZE), FLAG_ENTRY(WS_MAXIMIZEBOX),
497 FLAG_ENTRY(WS_MINIMIZE), FLAG_ENTRY(WS_MINIMIZEBOX),
498 FLAG_ENTRY(WS_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_POPUP),
499 FLAG_ENTRY(WS_POPUPWINDOW), FLAG_ENTRY(WS_SIZEBOX),
500 FLAG_ENTRY(WS_SYSMENU), FLAG_ENTRY(WS_TABSTOP), FLAG_ENTRY(WS_THICKFRAME),
501 FLAG_ENTRY(WS_TILED), FLAG_ENTRY(WS_TILEDWINDOW), FLAG_ENTRY(WS_VISIBLE),
502 FLAG_ENTRY(WS_VSCROLL)
503 };
504
505 return flagsValue(styleFlags, sizeof(styleFlags) / sizeof(styleFlags[0]), style);
506}
507
508static QString exStyleFlags(uint exStyle)
509{
510 static const QWinMessageMapping<uint> exStyleFlags[] = {
511 FLAG_ENTRY(WS_EX_ACCEPTFILES), FLAG_ENTRY(WS_EX_APPWINDOW),
512 FLAG_ENTRY(WS_EX_CLIENTEDGE), FLAG_ENTRY(WS_EX_DLGMODALFRAME),
513 FLAG_ENTRY(WS_EX_LEFT), FLAG_ENTRY(WS_EX_LEFTSCROLLBAR),
514 FLAG_ENTRY(WS_EX_LTRREADING), FLAG_ENTRY(WS_EX_MDICHILD),
515 FLAG_ENTRY(WS_EX_NOACTIVATE), FLAG_ENTRY(WS_EX_NOPARENTNOTIFY),
516 FLAG_ENTRY(WS_EX_OVERLAPPEDWINDOW), FLAG_ENTRY(WS_EX_PALETTEWINDOW),
517 FLAG_ENTRY(WS_EX_RIGHT), FLAG_ENTRY(WS_EX_RIGHTSCROLLBAR),
518 FLAG_ENTRY(WS_EX_RTLREADING), FLAG_ENTRY(WS_EX_STATICEDGE),
519 FLAG_ENTRY(WS_EX_TOOLWINDOW), FLAG_ENTRY(WS_EX_TOPMOST),
520 FLAG_ENTRY(WS_EX_TRANSPARENT), FLAG_ENTRY(WS_EX_WINDOWEDGE)
521 };
522
523 return flagsValue(exStyleFlags, sizeof(exStyleFlags) / sizeof(exStyleFlags[0]), exStyle);
524}
525
526static const char *imeCommand(uint cmd)
527{
528 static const QWinMessageMapping<uint> commands[] = {
529 FLAG_ENTRY(IMN_CHANGECANDIDATE), FLAG_ENTRY(IMN_CLOSECANDIDATE),
530 FLAG_ENTRY(IMN_CLOSESTATUSWINDOW), FLAG_ENTRY(IMN_GUIDELINE),
531 FLAG_ENTRY(IMN_OPENCANDIDATE), FLAG_ENTRY(IMN_OPENSTATUSWINDOW),
532 FLAG_ENTRY(IMN_SETCANDIDATEPOS), FLAG_ENTRY(IMN_SETCOMPOSITIONFONT),
533 FLAG_ENTRY(IMN_SETCOMPOSITIONWINDOW), FLAG_ENTRY(IMN_SETCONVERSIONMODE),
534 FLAG_ENTRY(IMN_SETOPENSTATUS), FLAG_ENTRY(IMN_SETSENTENCEMODE),
535 FLAG_ENTRY(IMN_SETSTATUSWINDOWPOS)
536 };
537
538 return findWinMessageMapping(commands, sizeof(commands) / sizeof(commands[0]), cmd);
539}
540
541static QString imeShowFlags(uint flags)
542{
543 static const QWinMessageMapping<uint> showFlags[] = {
544 FLAG_ENTRY(ISC_SHOWUICOMPOSITIONWINDOW),
545 FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW),
546 FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 1),
547 FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 2),
548 FLAG_ENTRY(ISC_SHOWUICANDIDATEWINDOW << 3)
549 };
550
551 return flagsValue(showFlags, sizeof(showFlags) / sizeof(showFlags[0]), flags);
552}
553
554static const char *wmSizeParam(uint p)
555{
556 static const QWinMessageMapping<uint> sizeParams[] = {
557 FLAG_ENTRY(SIZE_MAXHIDE), FLAG_ENTRY(SIZE_MAXIMIZED),
558 FLAG_ENTRY(SIZE_MAXSHOW), FLAG_ENTRY(SIZE_MINIMIZED),
559 FLAG_ENTRY(SIZE_RESTORED)
560 };
561
562 return findWinMessageMapping(sizeParams, sizeof(sizeParams) / sizeof(sizeParams[0]), p);
563}
564
565static QString virtualKeys(uint vk)
566{
567 static const QWinMessageMapping<uint> keys[] = {
568 FLAG_ENTRY(MK_CONTROL), FLAG_ENTRY(MK_LBUTTON), FLAG_ENTRY(MK_MBUTTON),
569 FLAG_ENTRY(MK_RBUTTON), FLAG_ENTRY(MK_SHIFT), FLAG_ENTRY(MK_XBUTTON1),
570 FLAG_ENTRY(MK_XBUTTON2)
571 };
572
573 return flagsValue(keys, sizeof(keys) / sizeof(keys[0]), vk);
574}
575
576static QString winPosFlags(uint f)
577{
578 static const QWinMessageMapping<uint> winPosValues[] = {
579 FLAG_ENTRY(SWP_DRAWFRAME), FLAG_ENTRY(SWP_FRAMECHANGED),
580 FLAG_ENTRY(SWP_HIDEWINDOW), FLAG_ENTRY(SWP_NOACTIVATE),
581 FLAG_ENTRY(SWP_NOCOPYBITS), FLAG_ENTRY(SWP_NOMOVE),
582 FLAG_ENTRY(SWP_NOOWNERZORDER), FLAG_ENTRY(SWP_NOREDRAW),
583 FLAG_ENTRY(SWP_NOREPOSITION), FLAG_ENTRY(SWP_NOSENDCHANGING),
584 FLAG_ENTRY(SWP_NOSIZE), FLAG_ENTRY(SWP_NOZORDER),
585 FLAG_ENTRY(SWP_SHOWWINDOW)
586 };
587
588 return flagsValue(winPosValues, sizeof(winPosValues) / sizeof(winPosValues[0]), f);
589}
590
591static const char *winPosInsertAfter(quintptr h)
592{
593 static const QWinMessageMapping<quintptr> insertAfterValues[] = {
594 {quintptr(HWND_BOTTOM), "HWND_BOTTOM"},
595 {quintptr(HWND_NOTOPMOST), "HWND_NOTOPMOST"},
596 {quintptr(HWND_TOP), "HWND_TOP"},
597 {quintptr(HWND_TOPMOST), "HWND_TOPMOST"}
598 };
599 return findWinMessageMapping(insertAfterValues, sizeof(insertAfterValues) / sizeof(insertAfterValues[0]), h);
600}
601
602static const char *sessionMgrLogOffOption(uint p)
603{
604#ifndef ENDSESSION_CLOSEAPP
605#define ENDSESSION_CLOSEAPP 0x00000001
606#endif
607#ifndef ENDSESSION_CRITICAL
608#define ENDSESSION_CRITICAL 0x40000000
609#endif
610 static const QWinMessageMapping<uint> values[] = {
611 {ENDSESSION_CLOSEAPP, "Close application"},
612 {ENDSESSION_CRITICAL, "Force application end"},
613 {ENDSESSION_LOGOFF, "User logoff"}
614 };
615
616 return findWinMessageMapping(values, sizeof(values) / sizeof(values[0]), p);
617}
618
619// Returns a "human readable" string representation of the MSG and the
620// information it points to
621QString decodeMSG(const MSG& msg)
622{
623 const WPARAM wParam = msg.wParam;
624 const LPARAM lParam = msg.lParam;
625
626 QString message;
627 // Custom WM_'s
628 if (msg.message > WM_APP)
629 message= QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
630 else if (msg.message > WM_USER)
631 message = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
632 else if (const char *wmmsgC = findWMstr(msg.message))
633 message = QString::fromLatin1(wmmsgC);
634 else
635 message = QString::fromLatin1("WM_(0x%1)").arg(msg.message, 0, 16); // Unknown WM_, so use number
636
637 // Yes, we want to give the WM_ names 20 chars of space before showing the
638 // decoded message, since some of the common messages are quite long, and
639 // we don't want the decoded information to vary in output position
640 if (message.size() < 20)
641 message.prepend(QString(20 - message.size(), u' '));
642 message += ": "_L1;
643
644 const QString hwndS = QString::asprintf("(%p)", reinterpret_cast<void *>(msg.hwnd));
645 const QString wParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(wParam));
646 const QString lParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(lParam));
647
648 QString parameters;
649 switch (msg.message) {
650 case WM_ACTIVATE:
651 if (const char *a = activateParameter(uint(wParam)))
652 parameters += QLatin1StringView(a);
653 parameters += " Hwnd "_L1 + hwndS;
654 break;
655 case WM_CAPTURECHANGED:
656 parameters = "Hwnd gaining capture "_L1 + hwndS;
657 break;
658 case WM_CREATE:
659 {
660 auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
661 QString className;
662 if (lpcs->lpszClass != nullptr) {
663 className = HIWORD(lpcs->lpszClass) == 0
664 ? QString::number(LOWORD(lpcs->lpszClass), 16) // Atom
665 : QString::fromWCharArray(lpcs->lpszClass);
666 }
667
668 const QString windowName = lpcs->lpszName
669 ? QString::fromWCharArray(lpcs->lpszName) : QString();
670
671 parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
672 lpcs->x, lpcs->y, lpcs->cx, lpcs->cy,
673 className.toLatin1().constData(),
674 windowName.toLatin1().constData(),
675 reinterpret_cast<void *>(lpcs->hwndParent),
676 styleFlags(uint(lpcs->style)).toLatin1().constData(),
677 exStyleFlags(lpcs->dwExStyle).toLatin1().constData());
678 }
679 break;
680 case WM_DESTROY:
681 parameters = "Destroy hwnd "_L1 + hwndS;
682 break;
683 case 0x02E0u: { // WM_DPICHANGED
684 auto rect = reinterpret_cast<const RECT *>(lParam);
685 QTextStream(&parameters) << "DPI: " << HIWORD(wParam) << ','
686 << LOWORD(wParam) << ' ' << (rect->right - rect->left) << 'x'
687 << (rect->bottom - rect->top) << Qt::forcesign << rect->left << rect->top;
688 }
689 break;
690 case WM_IME_NOTIFY:
691 {
692 parameters = "Command("_L1;
693 if (const char *c = imeCommand(uint(wParam)))
694 parameters += QLatin1StringView(c);
695 parameters += " : "_L1 + lParamS;
696 }
697 break;
698 case WM_IME_SETCONTEXT:
699 parameters = "Input context("_L1
700 + (wParam ? "Active"_L1 : "Inactive"_L1)
701 + ") Show flags("_L1
702 + imeShowFlags(DWORD(lParam)) + u')';
703 break;
704 case WM_KILLFOCUS:
705 parameters = "Hwnd gaining keyboard focus "_L1 + wParamS;
706 break;
707 case WM_CHAR:
708 case WM_IME_CHAR:
709 case WM_KEYDOWN:
710 case WM_KEYUP:
711 {
712 const int nVirtKey = int(wParam);
713 const long lKeyData = long(lParam);
714 int repCount = (lKeyData & 0xffff); // Bit 0-15
715 int scanCode = (lKeyData & 0xf0000) >> 16; // Bit 16-23
716 bool contextCode = !!(lKeyData & 0x20000000); // Bit 29
717 bool prevState = !!(lKeyData & 0x40000000); // Bit 30
718 bool transState = !!(lKeyData & 0x80000000); // Bit 31
719 parameters = QString::asprintf("Virtual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
720 nVirtKey, scanCode, repCount,
721 contextCode, prevState, transState);
722 }
723 break;
724 case WM_INPUTLANGCHANGE:
725 parameters = QStringLiteral("Keyboard layout changed");
726 break;
727 case WM_NCACTIVATE:
728 parameters = (msg.wParam? "Active Titlebar"_L1 : "Inactive Titlebar"_L1);
729 break;
730 case WM_MOUSEACTIVATE:
731 {
732 const char *mouseMsg = findWMstr(HIWORD(lParam));
733 parameters = QString::asprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)",
734 reinterpret_cast<void *>(wParam),
735 LOWORD(lParam), mouseMsg ? mouseMsg : "");
736 }
737 break;
738 case WM_MOUSELEAVE:
739 break; // wParam & lParam not used
740 case WM_MOUSEHOVER:
741 case WM_MOUSEWHEEL:
742 case WM_MOUSEHWHEEL:
743 case WM_LBUTTONDBLCLK:
744 case WM_LBUTTONDOWN:
745 case WM_LBUTTONUP:
746 case WM_MBUTTONDBLCLK:
747 case WM_MBUTTONDOWN:
748 case WM_MBUTTONUP:
749 case WM_RBUTTONDBLCLK:
750 case WM_RBUTTONDOWN:
751 case WM_RBUTTONUP:
752 case WM_MOUSEMOVE:
753 parameters = QString::asprintf("x,y(%4d,%4d) Virtual Keys(",
754 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
755 + virtualKeys(uint(wParam)) + u')';
756 break;
757 case WM_MOVE:
758 parameters = QString::asprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
759 break;
760 case WM_ERASEBKGND:
761 case WM_PAINT:
762 parameters = "hdc"_L1 + wParamS;
763 break;
764 case WM_QUERYNEWPALETTE:
765 break; // lParam & wParam are unused
766 case WM_SETCURSOR:
767 parameters = QString::asprintf("HitTestCode(0x%x) MouseMsg(", LOWORD(lParam));
768 if (const char *mouseMsg = findWMstr(HIWORD(lParam)))
769 parameters += QLatin1StringView(mouseMsg);
770 parameters += u')';
771 break;
772 case WM_SETFOCUS:
773 parameters = "Lost Focus "_L1 + wParamS;
774 break;
775 case WM_SETTEXT:
776 parameters = "Set Text ("_L1
777 + QString::fromWCharArray(reinterpret_cast<const wchar_t *>(lParam))
778 + u')';
779 break;
780 case WM_SIZE:
781 parameters = QString::asprintf("w,h(%4d,%4d) showmode(",
782 LOWORD(lParam), HIWORD(lParam));
783 if (const char *showMode = wmSizeParam(uint(wParam)))
784 parameters += QLatin1StringView(showMode);
785 parameters += u')';
786 break;
787 case WM_WINDOWPOSCHANGED:
788 {
789 auto winPos = reinterpret_cast<LPWINDOWPOS>(lParam);
790 if (!winPos)
791 break;
792 const auto insertAfter = quintptr(winPos->hwndInsertAfter);
793 parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(",
794 winPos->x, winPos->y, winPos->cx, winPos->cy,
795 winPosFlags(winPos->flags).toLatin1().constData());
796 if (const char *h = winPosInsertAfter(insertAfter))
797 parameters += QLatin1StringView(h);
798 else
799 parameters += QString::number(insertAfter, 16);
800 parameters += u')';
801 }
802 break;
803 case WM_QUERYENDSESSION:
804 parameters = "End session: "_L1;
805 if (const char *logoffOption = sessionMgrLogOffOption(uint(wParam)))
806 parameters += QLatin1StringView(logoffOption);
807 break;
808 case WM_SETTINGCHANGE:
809 parameters = "wParam"_L1 + wParamS + " lParam("_L1
810 + QString::fromWCharArray(reinterpret_cast<LPCWSTR>(lParam)) + u')';
811 break;
812 default:
813 parameters = "wParam"_L1 + wParamS + " lParam"_L1 + lParamS;
814 break;
815 }
816
817 return message + "hwnd"_L1 + hwndS + u' ' + parameters;
818}
819
820QDebug operator<<(QDebug dbg, const MSG &msg)
821{
822 QDebugStateSaver saver(dbg);
823 dbg.noquote();
824 dbg.nospace();
825 dbg << decodeMSG(msg);
826 return dbg;
827}
828#endif
829
830#endif // QT_NO_QOBJECT
831
832#ifndef QT_NO_QOBJECT
833void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
834{
835 QThreadData *data = object->d_func()->threadData.loadRelaxed();
836
837 const auto locker = qt_scoped_lock(data->postEventList.mutex);
838 if (data->postEventList.size() == 0)
839 return;
840 for (int i = 0; i < data->postEventList.size(); ++i) {
841 const QPostEvent &pe = data->postEventList.at(i);
842 if (pe.receiver == object
843 && pe.event
844 && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
845 && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
846 --pe.receiver->d_func()->postedEvents;
847 pe.event->m_posted = false;
848 delete pe.event;
849 const_cast<QPostEvent &>(pe).event = 0;
850 return;
851 }
852 }
853}
854#endif // QT_NO_QOBJECT
855
857{
858 const HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
859 return h != NULL && h != INVALID_HANDLE_VALUE;
860}
861
862void QCoreApplicationPrivate::initDebuggingConsole()
863{
864 if (hasValidStdOutHandle())
865 return;
866 const QString env = qEnvironmentVariable("QT_WIN_DEBUG_CONSOLE");
867 if (env.isEmpty())
868 return;
869 if (env.compare(u"new"_s, Qt::CaseInsensitive) == 0) {
870 if (AllocConsole() == FALSE)
871 return;
872 consoleAllocated = true;
873 } else if (env.compare(u"attach"_s, Qt::CaseInsensitive) == 0) {
874 // If the calling process is already attached to a console,
875 // the error code returned is ERROR_ACCESS_DENIED.
876 if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::GetLastError() != ERROR_ACCESS_DENIED)
877 return;
878 } else {
879 // Unknown input, don't make any decision for the user.
880 return;
881 }
882 // The std{in,out,err} handles are read-only, so we need to pass in dummies.
883 FILE *in = nullptr;
884 FILE *out = nullptr;
885 FILE *err = nullptr;
886 freopen_s(&in, "CONIN$", "r", stdin);
887 freopen_s(&out, "CONOUT$", "w", stdout);
888 freopen_s(&err, "CONOUT$", "w", stderr);
889 // However, things wouldn't work if the runtime did not preserve the pointers.
890 Q_ASSERT(in == stdin);
891 Q_ASSERT(out == stdout);
892 Q_ASSERT(err == stderr);
893}
894
895void QCoreApplicationPrivate::cleanupDebuggingConsole()
896{
897 if (consoleAllocated)
898 FreeConsole();
899}
900
901QT_END_NAMESPACE
static bool hasValidStdOutHandle()
QString qAppFileName()