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
622QString decodeMSG(const MSG& msg)
623{
624 const WPARAM wParam = msg.wParam;
625 const LPARAM lParam = msg.lParam;
626
627 QString message;
628 // Custom WM_'s
629 if (msg.message > WM_APP)
630 message= QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
631 else if (msg.message > WM_USER)
632 message = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
633 else if (const char *wmmsgC = findWMstr(msg.message))
634 message = QString::fromLatin1(wmmsgC);
635 else
636 message = QString::fromLatin1("WM_(0x%1)").arg(msg.message, 0, 16); // Unknown WM_, so use number
637
638 // Yes, we want to give the WM_ names 20 chars of space before showing the
639 // decoded message, since some of the common messages are quite long, and
640 // we don't want the decoded information to vary in output position
641 if (message.size() < 20)
642 message.prepend(QString(20 - message.size(), u' '));
643 message += ": "_L1;
644
645 const QString hwndS = QString::asprintf("(%p)", reinterpret_cast<void *>(msg.hwnd));
646 const QString wParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(wParam));
647 const QString lParamS = QString::asprintf("(%p)", reinterpret_cast<void *>(lParam));
648
649 QString parameters;
650 switch (msg.message) {
651 case WM_ACTIVATE:
652 if (const char *a = activateParameter(uint(wParam)))
653 parameters += QLatin1StringView(a);
654 parameters += " Hwnd "_L1 + hwndS;
655 break;
656 case WM_CAPTURECHANGED:
657 parameters = "Hwnd gaining capture "_L1 + hwndS;
658 break;
659 case WM_CREATE:
660 {
661 auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
662 QString className;
663 if (lpcs->lpszClass != nullptr) {
664 className = HIWORD(lpcs->lpszClass) == 0
665 ? QString::number(LOWORD(lpcs->lpszClass), 16) // Atom
666 : QString::fromWCharArray(lpcs->lpszClass);
667 }
668
669 const QString windowName = lpcs->lpszName
670 ? QString::fromWCharArray(lpcs->lpszName) : QString();
671
672 parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
673 lpcs->x, lpcs->y, lpcs->cx, lpcs->cy,
674 className.toLatin1().constData(),
675 windowName.toLatin1().constData(),
676 reinterpret_cast<void *>(lpcs->hwndParent),
677 styleFlags(uint(lpcs->style)).toLatin1().constData(),
678 exStyleFlags(lpcs->dwExStyle).toLatin1().constData());
679 }
680 break;
681 case WM_DESTROY:
682 parameters = "Destroy hwnd "_L1 + hwndS;
683 break;
684 case 0x02E0u: { // WM_DPICHANGED
685 auto rect = reinterpret_cast<const RECT *>(lParam);
686 QTextStream(&parameters) << "DPI: " << HIWORD(wParam) << ','
687 << LOWORD(wParam) << ' ' << (rect->right - rect->left) << 'x'
688 << (rect->bottom - rect->top) << Qt::forcesign << rect->left << rect->top;
689 }
690 break;
691 case WM_IME_NOTIFY:
692 {
693 parameters = "Command("_L1;
694 if (const char *c = imeCommand(uint(wParam)))
695 parameters += QLatin1StringView(c);
696 parameters += " : "_L1 + lParamS;
697 }
698 break;
699 case WM_IME_SETCONTEXT:
700 parameters = "Input context("_L1
701 + (wParam ? "Active"_L1 : "Inactive"_L1)
702 + ") Show flags("_L1
703 + imeShowFlags(DWORD(lParam)) + u')';
704 break;
705 case WM_KILLFOCUS:
706 parameters = "Hwnd gaining keyboard focus "_L1 + wParamS;
707 break;
708 case WM_CHAR:
709 case WM_IME_CHAR:
710 case WM_KEYDOWN:
711 case WM_KEYUP:
712 {
713 const int nVirtKey = int(wParam);
714 const long lKeyData = long(lParam);
715 int repCount = (lKeyData & 0xffff); // Bit 0-15
716 int scanCode = (lKeyData & 0xf0000) >> 16; // Bit 16-23
717 bool contextCode = !!(lKeyData & 0x20000000); // Bit 29
718 bool prevState = !!(lKeyData & 0x40000000); // Bit 30
719 bool transState = !!(lKeyData & 0x80000000); // Bit 31
720 parameters = QString::asprintf("Virtual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
721 nVirtKey, scanCode, repCount,
722 contextCode, prevState, transState);
723 }
724 break;
725 case WM_INPUTLANGCHANGE:
726 parameters = QStringLiteral("Keyboard layout changed");
727 break;
728 case WM_NCACTIVATE:
729 parameters = (msg.wParam? "Active Titlebar"_L1 : "Inactive Titlebar"_L1);
730 break;
731 case WM_MOUSEACTIVATE:
732 {
733 const char *mouseMsg = findWMstr(HIWORD(lParam));
734 parameters = QString::asprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)",
735 reinterpret_cast<void *>(wParam),
736 LOWORD(lParam), mouseMsg ? mouseMsg : "");
737 }
738 break;
739 case WM_MOUSELEAVE:
740 break; // wParam & lParam not used
741 case WM_MOUSEHOVER:
742 case WM_MOUSEWHEEL:
743 case WM_MOUSEHWHEEL:
744 case WM_LBUTTONDBLCLK:
745 case WM_LBUTTONDOWN:
746 case WM_LBUTTONUP:
747 case WM_MBUTTONDBLCLK:
748 case WM_MBUTTONDOWN:
749 case WM_MBUTTONUP:
750 case WM_RBUTTONDBLCLK:
751 case WM_RBUTTONDOWN:
752 case WM_RBUTTONUP:
753 case WM_MOUSEMOVE:
754 parameters = QString::asprintf("x,y(%4d,%4d) Virtual Keys(",
755 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))
756 + virtualKeys(uint(wParam)) + u')';
757 break;
758 case WM_MOVE:
759 parameters = QString::asprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
760 break;
761 case WM_ERASEBKGND:
762 case WM_PAINT:
763 parameters = "hdc"_L1 + wParamS;
764 break;
765 case WM_QUERYNEWPALETTE:
766 break; // lParam & wParam are unused
767 case WM_SETCURSOR:
768 parameters = QString::asprintf("HitTestCode(0x%x) MouseMsg(", LOWORD(lParam));
769 if (const char *mouseMsg = findWMstr(HIWORD(lParam)))
770 parameters += QLatin1StringView(mouseMsg);
771 parameters += u')';
772 break;
773 case WM_SETFOCUS:
774 parameters = "Lost Focus "_L1 + wParamS;
775 break;
776 case WM_SETTEXT:
777 parameters = "Set Text ("_L1
778 + QString::fromWCharArray(reinterpret_cast<const wchar_t *>(lParam))
779 + u')';
780 break;
781 case WM_SIZE:
782 parameters = QString::asprintf("w,h(%4d,%4d) showmode(",
783 LOWORD(lParam), HIWORD(lParam));
784 if (const char *showMode = wmSizeParam(uint(wParam)))
785 parameters += QLatin1StringView(showMode);
786 parameters += u')';
787 break;
788 case WM_WINDOWPOSCHANGED:
789 {
790 auto winPos = reinterpret_cast<LPWINDOWPOS>(lParam);
791 if (!winPos)
792 break;
793 const auto insertAfter = quintptr(winPos->hwndInsertAfter);
794 parameters = QString::asprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(",
795 winPos->x, winPos->y, winPos->cx, winPos->cy,
796 winPosFlags(winPos->flags).toLatin1().constData());
797 if (const char *h = winPosInsertAfter(insertAfter))
798 parameters += QLatin1StringView(h);
799 else
800 parameters += QString::number(insertAfter, 16);
801 parameters += u')';
802 }
803 break;
804 case WM_QUERYENDSESSION:
805 parameters = "End session: "_L1;
806 if (const char *logoffOption = sessionMgrLogOffOption(uint(wParam)))
807 parameters += QLatin1StringView(logoffOption);
808 break;
809 case WM_SETTINGCHANGE:
810 parameters = "wParam"_L1 + wParamS + " lParam("_L1
811 + QString::fromWCharArray(reinterpret_cast<LPCWSTR>(lParam)) + u')';
812 break;
813 default:
814 parameters = "wParam"_L1 + wParamS + " lParam"_L1 + lParamS;
815 break;
816 }
817
818 return message + "hwnd"_L1 + hwndS + u' ' + parameters;
819}
820
821QDebug operator<<(QDebug dbg, const MSG &msg)
822{
823 QDebugStateSaver saver(dbg);
824 dbg.noquote();
825 dbg.nospace();
826 dbg << decodeMSG(msg);
827 return dbg;
828}
829#endif
830
831#endif // QT_NO_QOBJECT
832
833#ifndef QT_NO_QOBJECT
834void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
835{
836 QThreadData *data = object->d_func()->threadData.loadRelaxed();
837
838 const auto locker = qt_scoped_lock(data->postEventList.mutex);
839 if (data->postEventList.size() == 0)
840 return;
841 for (int i = 0; i < data->postEventList.size(); ++i) {
842 const QPostEvent &pe = data->postEventList.at(i);
843 if (pe.receiver == object
844 && pe.event
845 && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
846 && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
847 --pe.receiver->d_func()->postedEvents;
848 pe.event->m_posted = false;
849 delete pe.event;
850 const_cast<QPostEvent &>(pe).event = 0;
851 return;
852 }
853 }
854}
855#endif // QT_NO_QOBJECT
856
858{
859 const HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
860 return h != NULL && h != INVALID_HANDLE_VALUE;
861}
862
863void QCoreApplicationPrivate::initDebuggingConsole()
864{
865 if (hasValidStdOutHandle())
866 return;
867 const QString env = qEnvironmentVariable("QT_WIN_DEBUG_CONSOLE");
868 if (env.isEmpty())
869 return;
870 if (env.compare(u"new"_s, Qt::CaseInsensitive) == 0) {
871 if (AllocConsole() == FALSE)
872 return;
873 consoleAllocated = true;
874 } else if (env.compare(u"attach"_s, Qt::CaseInsensitive) == 0) {
875 // If the calling process is already attached to a console,
876 // the error code returned is ERROR_ACCESS_DENIED.
877 if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::GetLastError() != ERROR_ACCESS_DENIED)
878 return;
879 } else {
880 // Unknown input, don't make any decision for the user.
881 return;
882 }
883 // The std{in,out,err} handles are read-only, so we need to pass in dummies.
884 FILE *in = nullptr;
885 FILE *out = nullptr;
886 FILE *err = nullptr;
887 freopen_s(&in, "CONIN$", "r", stdin);
888 freopen_s(&out, "CONOUT$", "w", stdout);
889 freopen_s(&err, "CONOUT$", "w", stderr);
890 // However, things wouldn't work if the runtime did not preserve the pointers.
891 Q_ASSERT(in == stdin);
892 Q_ASSERT(out == stdout);
893 Q_ASSERT(err == stderr);
894}
895
896void QCoreApplicationPrivate::cleanupDebuggingConsole()
897{
898 if (consoleAllocated)
899 FreeConsole();
900}
901
902QT_END_NAMESPACE
Combined button and popup list for selecting options.
static bool hasValidStdOutHandle()
QString qAppFileName()