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