1 | /* $Id: main.cpp 42665 2012-08-07 14:55:09Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | *
|
---|
4 | * VBox frontends: Qt GUI ("VirtualBox"):
|
---|
5 | * The main() function
|
---|
6 | */
|
---|
7 |
|
---|
8 | /*
|
---|
9 | * Copyright (C) 2006-2009 Oracle Corporation
|
---|
10 | *
|
---|
11 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
12 | * available from http://www.virtualbox.org. This file is free software;
|
---|
13 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
14 | * General Public License (GPL) as published by the Free Software
|
---|
15 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
16 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
17 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
18 | */
|
---|
19 |
|
---|
20 | #ifdef VBOX_WITH_PRECOMPILED_HEADERS
|
---|
21 | #include "precomp.h"
|
---|
22 | #ifdef Q_WS_MAC
|
---|
23 | # include "UICocoaApplication.h"
|
---|
24 | #endif /* Q_WS_MAC */
|
---|
25 | #else /* !VBOX_WITH_PRECOMPILED_HEADERS */
|
---|
26 | #include "VBoxGlobal.h"
|
---|
27 | #include "UIMessageCenter.h"
|
---|
28 | #include "UISelectorWindow.h"
|
---|
29 | #include "VBoxUtils.h"
|
---|
30 | #ifdef Q_WS_MAC
|
---|
31 | # include "UICocoaApplication.h"
|
---|
32 | #endif
|
---|
33 |
|
---|
34 | #ifdef Q_WS_X11
|
---|
35 | #include <QFontDatabase>
|
---|
36 | #include <iprt/env.h>
|
---|
37 | #endif
|
---|
38 |
|
---|
39 | #include <QCleanlooksStyle>
|
---|
40 | #include <QPlastiqueStyle>
|
---|
41 | #include <QMessageBox>
|
---|
42 | #include <QLocale>
|
---|
43 | #include <QTranslator>
|
---|
44 |
|
---|
45 | #ifdef Q_WS_X11
|
---|
46 | # include <X11/Xlib.h>
|
---|
47 | #endif
|
---|
48 |
|
---|
49 | #include <iprt/buildconfig.h>
|
---|
50 | #include <iprt/err.h>
|
---|
51 | #include <iprt/initterm.h>
|
---|
52 | #include <iprt/process.h>
|
---|
53 | #include <iprt/stream.h>
|
---|
54 | #include <VBox/err.h>
|
---|
55 | #include <VBox/version.h>
|
---|
56 | #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
|
---|
57 |
|
---|
58 | #ifdef VBOX_WITH_HARDENING
|
---|
59 | # include <VBox/sup.h>
|
---|
60 | #endif
|
---|
61 |
|
---|
62 | #ifdef RT_OS_LINUX
|
---|
63 | # include <unistd.h>
|
---|
64 | #endif
|
---|
65 |
|
---|
66 | #include <cstdio>
|
---|
67 |
|
---|
68 | /* XXX Temporarily. Don't rely on the user to hack the Makefile himself! */
|
---|
69 | QString g_QStrHintLinuxNoMemory = QApplication::tr(
|
---|
70 | "This error means that the kernel driver was either not able to "
|
---|
71 | "allocate enough memory or that some mapping operation failed."
|
---|
72 | );
|
---|
73 |
|
---|
74 | QString g_QStrHintLinuxNoDriver = QApplication::tr(
|
---|
75 | "The VirtualBox Linux kernel driver (vboxdrv) is either not loaded or "
|
---|
76 | "there is a permission problem with /dev/vboxdrv. Please reinstall the kernel "
|
---|
77 | "module by executing<br/><br/>"
|
---|
78 | " <font color=blue>'/etc/init.d/vboxdrv setup'</font><br/><br/>"
|
---|
79 | "as root. If it is available in your distribution, you should install the "
|
---|
80 | "DKMS package first. This package keeps track of Linux kernel changes and "
|
---|
81 | "recompiles the vboxdrv kernel module if necessary."
|
---|
82 | );
|
---|
83 |
|
---|
84 | QString g_QStrHintOtherWrongDriverVersion = QApplication::tr(
|
---|
85 | "The VirtualBox kernel modules do not match this version of "
|
---|
86 | "VirtualBox. The installation of VirtualBox was apparently not "
|
---|
87 | "successful. Please try completely uninstalling and reinstalling "
|
---|
88 | "VirtualBox."
|
---|
89 | );
|
---|
90 |
|
---|
91 | QString g_QStrHintLinuxWrongDriverVersion = QApplication::tr(
|
---|
92 | "The VirtualBox kernel modules do not match this version of "
|
---|
93 | "VirtualBox. The installation of VirtualBox was apparently not "
|
---|
94 | "successful. Executing<br/><br/>"
|
---|
95 | " <font color=blue>'/etc/init.d/vboxdrv setup'</font><br/><br/>"
|
---|
96 | "may correct this. Make sure that you do not mix the "
|
---|
97 | "OSE version and the PUEL version of VirtualBox."
|
---|
98 | );
|
---|
99 |
|
---|
100 | QString g_QStrHintOtherNoDriver = QApplication::tr(
|
---|
101 | "Make sure the kernel module has been loaded successfully."
|
---|
102 | );
|
---|
103 |
|
---|
104 | /* I hope this isn't (C), (TM) or (R) Microsoft support ;-) */
|
---|
105 | QString g_QStrHintReinstall = QApplication::tr(
|
---|
106 | "Please try reinstalling VirtualBox."
|
---|
107 | );
|
---|
108 |
|
---|
109 | #if defined(DEBUG) && defined(Q_WS_X11) && defined(RT_OS_LINUX)
|
---|
110 |
|
---|
111 | #include <signal.h>
|
---|
112 | #include <execinfo.h>
|
---|
113 |
|
---|
114 | /* get REG_EIP from ucontext.h */
|
---|
115 | #ifndef __USE_GNU
|
---|
116 | #define __USE_GNU
|
---|
117 | #endif
|
---|
118 | #include <ucontext.h>
|
---|
119 | #ifdef RT_ARCH_AMD64
|
---|
120 | # define REG_PC REG_RIP
|
---|
121 | #else
|
---|
122 | # define REG_PC REG_EIP
|
---|
123 | #endif
|
---|
124 |
|
---|
125 |
|
---|
126 |
|
---|
127 | /**
|
---|
128 | * the signal handler that prints out a backtrace of the call stack.
|
---|
129 | * the code is taken from http://www.linuxjournal.com/article/6391.
|
---|
130 | */
|
---|
131 | void bt_sighandler (int sig, siginfo_t *info, void *secret) {
|
---|
132 |
|
---|
133 | void *trace[16];
|
---|
134 | char **messages = (char **)NULL;
|
---|
135 | int i, trace_size = 0;
|
---|
136 | ucontext_t *uc = (ucontext_t *)secret;
|
---|
137 |
|
---|
138 | /* Do something useful with siginfo_t */
|
---|
139 | if (sig == SIGSEGV)
|
---|
140 | Log (("GUI: Got signal %d, faulty address is %p, from %p\n",
|
---|
141 | sig, info->si_addr, uc->uc_mcontext.gregs[REG_PC]));
|
---|
142 | else
|
---|
143 | Log (("GUI: Got signal %d\n", sig));
|
---|
144 |
|
---|
145 | trace_size = backtrace (trace, 16);
|
---|
146 | /* overwrite sigaction with caller's address */
|
---|
147 | trace[1] = (void *) uc->uc_mcontext.gregs [REG_PC];
|
---|
148 |
|
---|
149 | messages = backtrace_symbols (trace, trace_size);
|
---|
150 | /* skip first stack frame (points here) */
|
---|
151 | Log (("GUI: [bt] Execution path:\n"));
|
---|
152 | for (i = 1; i < trace_size; ++i)
|
---|
153 | Log (("GUI: [bt] %s\n", messages[i]));
|
---|
154 |
|
---|
155 | exit (0);
|
---|
156 | }
|
---|
157 |
|
---|
158 | #endif /* DEBUG && X11 && LINUX*/
|
---|
159 |
|
---|
160 | #if defined(RT_OS_DARWIN)
|
---|
161 | # include <dlfcn.h>
|
---|
162 | # include <sys/mman.h>
|
---|
163 | # include <iprt/asm.h>
|
---|
164 | # include <iprt/system.h>
|
---|
165 |
|
---|
166 | /** Really ugly hack to shut up a silly check in AppKit. */
|
---|
167 | static void ShutUpAppKit(void)
|
---|
168 | {
|
---|
169 | /* Check for Snow Leopard or higher */
|
---|
170 | char szInfo[64];
|
---|
171 | int rc = RTSystemQueryOSInfo (RTSYSOSINFO_RELEASE, szInfo, sizeof(szInfo));
|
---|
172 | if ( RT_SUCCESS (rc)
|
---|
173 | && szInfo[0] == '1') /* higher than 1x.x.x */
|
---|
174 | {
|
---|
175 | /*
|
---|
176 | * Find issetguid() and make it always return 0 by modifying the code.
|
---|
177 | */
|
---|
178 | void *addr = dlsym(RTLD_DEFAULT, "issetugid");
|
---|
179 | int rc = mprotect((void *)((uintptr_t)addr & ~(uintptr_t)0xfff), 0x2000, PROT_WRITE|PROT_READ|PROT_EXEC);
|
---|
180 | if (!rc)
|
---|
181 | ASMAtomicWriteU32((volatile uint32_t *)addr, 0xccc3c031); /* xor eax, eax; ret; int3 */
|
---|
182 | }
|
---|
183 | }
|
---|
184 | #endif /* DARWIN */
|
---|
185 |
|
---|
186 | static void QtMessageOutput (QtMsgType type, const char *msg)
|
---|
187 | {
|
---|
188 | #ifndef Q_WS_X11
|
---|
189 | NOREF(msg);
|
---|
190 | #endif
|
---|
191 | switch (type)
|
---|
192 | {
|
---|
193 | case QtDebugMsg:
|
---|
194 | Log (("Qt DEBUG: %s\n", msg));
|
---|
195 | break;
|
---|
196 | case QtWarningMsg:
|
---|
197 | Log (("Qt WARNING: %s\n", msg));
|
---|
198 | #ifdef Q_WS_X11
|
---|
199 | /* Needed for instance for the message ``cannot connect to X server'' */
|
---|
200 | RTStrmPrintf(g_pStdErr, "Qt WARNING: %s\n", msg);
|
---|
201 | #endif
|
---|
202 | break;
|
---|
203 | case QtCriticalMsg:
|
---|
204 | Log (("Qt CRITICAL: %s\n", msg));
|
---|
205 | #ifdef Q_WS_X11
|
---|
206 | /* Needed for instance for the message ``cannot connect to X server'' */
|
---|
207 | RTStrmPrintf(g_pStdErr, "Qt CRITICAL: %s\n", msg);
|
---|
208 | #endif
|
---|
209 | break;
|
---|
210 | case QtFatalMsg:
|
---|
211 | Log (("Qt FATAL: %s\n", msg));
|
---|
212 | #ifdef Q_WS_X11
|
---|
213 | RTStrmPrintf(g_pStdErr, "Qt FATAL: %s\n", msg);
|
---|
214 | #endif
|
---|
215 | }
|
---|
216 | }
|
---|
217 |
|
---|
218 | /**
|
---|
219 | * Show all available command line parameters.
|
---|
220 | */
|
---|
221 | static void showHelp()
|
---|
222 | {
|
---|
223 | QString mode = "", dflt = "";
|
---|
224 | #ifdef VBOX_GUI_USE_SDL
|
---|
225 | mode += "sdl";
|
---|
226 | #endif
|
---|
227 | #ifdef VBOX_GUI_USE_QIMAGE
|
---|
228 | if (!mode.isEmpty())
|
---|
229 | mode += "|";
|
---|
230 | mode += "image";
|
---|
231 | #endif
|
---|
232 | #ifdef VBOX_GUI_USE_DDRAW
|
---|
233 | if (!mode.isEmpty())
|
---|
234 | mode += "|";
|
---|
235 | mode += "ddraw";
|
---|
236 | #endif
|
---|
237 | #ifdef VBOX_GUI_USE_QUARTZ2D
|
---|
238 | if (!mode.isEmpty())
|
---|
239 | mode += "|";
|
---|
240 | mode += "quartz2d";
|
---|
241 | #endif
|
---|
242 | #if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
|
---|
243 | dflt = "quartz2d";
|
---|
244 | #elif (defined (Q_WS_WIN32) || defined (Q_WS_PM)) && defined (VBOX_GUI_USE_QIMAGE)
|
---|
245 | dflt = "image";
|
---|
246 | #elif defined (Q_WS_X11) && defined (VBOX_GUI_USE_SDL)
|
---|
247 | dflt = "sdl";
|
---|
248 | #else
|
---|
249 | dflt = "image";
|
---|
250 | #endif
|
---|
251 |
|
---|
252 | RTPrintf(VBOX_PRODUCT " Manager %s\n"
|
---|
253 | "(C) 2005-" VBOX_C_YEAR " " VBOX_VENDOR "\n"
|
---|
254 | "All rights reserved.\n"
|
---|
255 | "\n"
|
---|
256 | "Usage:\n"
|
---|
257 | " --startvm <vmname|UUID> start a VM by specifying its UUID or name\n"
|
---|
258 | " --seamless switch to seamless mode during startup\n"
|
---|
259 | " --fullscreen switch to fullscreen mode during startup\n"
|
---|
260 | " --rmode %-18s select different render mode (default is %s)\n"
|
---|
261 | " --no-startvm-errormsgbox do not show a message box for VM start errors\n"
|
---|
262 | # ifdef VBOX_GUI_WITH_PIDFILE
|
---|
263 | " --pidfile <file> create a pidfile file when a VM is up and running\n"
|
---|
264 | # endif
|
---|
265 | # ifdef VBOX_WITH_DEBUGGER_GUI
|
---|
266 | " --dbg enable the GUI debug menu\n"
|
---|
267 | " --debug like --dbg and show debug windows at VM startup\n"
|
---|
268 | " --debug-command-line like --dbg and show command line window at VM startup\n"
|
---|
269 | " --debug-statistics like --dbg and show statistics window at VM startup\n"
|
---|
270 | " --no-debug disable the GUI debug menu and debug windows\n"
|
---|
271 | " --start-paused start the VM in the paused state\n"
|
---|
272 | " --start-running start the VM running (for overriding --debug*)\n"
|
---|
273 | "\n"
|
---|
274 | # endif
|
---|
275 | "Expert options:\n"
|
---|
276 | " --disable-patm disable code patching (ignored by AMD-V/VT-x)\n"
|
---|
277 | " --disable-csam disable code scanning (ignored by AMD-V/VT-x)\n"
|
---|
278 | " --recompile-supervisor recompiled execution of supervisor code (*)\n"
|
---|
279 | " --recompile-user recompiled execution of user code (*)\n"
|
---|
280 | " --recompile-all recompiled execution of all code, with disabled\n"
|
---|
281 | " code patching and scanning\n"
|
---|
282 | " --warp-pct <pct> time warp factor, 100%% (= 1.0) = normal speed\n"
|
---|
283 | " (*) For AMD-V/VT-x setups the effect is --recompile-all.\n"
|
---|
284 | "\n"
|
---|
285 | # ifdef VBOX_WITH_DEBUGGER_GUI
|
---|
286 | "The following environment (and extra data) variables are evaluated:\n"
|
---|
287 | " VBOX_GUI_DBG_ENABLED (GUI/Dbg/Enabled)\n"
|
---|
288 | " enable the GUI debug menu if set\n"
|
---|
289 | " VBOX_GUI_DBG_AUTO_SHOW (GUI/Dbg/AutoShow)\n"
|
---|
290 | " show debug windows at VM startup\n"
|
---|
291 | " VBOX_GUI_NO_DEBUGGER disable the GUI debug menu and debug windows\n"
|
---|
292 | # endif
|
---|
293 | "\n",
|
---|
294 | RTBldCfgVersion(),
|
---|
295 | mode.toLatin1().constData(),
|
---|
296 | dflt.toLatin1().constData());
|
---|
297 | /** @todo Show this as a dialog on windows. */
|
---|
298 | }
|
---|
299 |
|
---|
300 | extern "C" DECLEXPORT(int) TrustedMain (int argc, char **argv, char ** /*envp*/)
|
---|
301 | {
|
---|
302 | LogFlowFuncEnter();
|
---|
303 | # if defined(RT_OS_DARWIN)
|
---|
304 | ShutUpAppKit();
|
---|
305 | # endif
|
---|
306 |
|
---|
307 | for (int i=0; i<argc; i++)
|
---|
308 | if ( !strcmp(argv[i], "-h")
|
---|
309 | || !strcmp(argv[i], "-?")
|
---|
310 | || !strcmp(argv[i], "-help")
|
---|
311 | || !strcmp(argv[i], "--help"))
|
---|
312 | {
|
---|
313 | showHelp();
|
---|
314 | return 0;
|
---|
315 | }
|
---|
316 |
|
---|
317 | #if defined(DEBUG) && defined(Q_WS_X11) && defined(RT_OS_LINUX)
|
---|
318 | /* install our signal handler to backtrace the call stack */
|
---|
319 | struct sigaction sa;
|
---|
320 | sa.sa_sigaction = bt_sighandler;
|
---|
321 | sigemptyset (&sa.sa_mask);
|
---|
322 | sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
---|
323 | sigaction (SIGSEGV, &sa, NULL);
|
---|
324 | sigaction (SIGBUS, &sa, NULL);
|
---|
325 | sigaction (SIGUSR1, &sa, NULL);
|
---|
326 | #endif
|
---|
327 |
|
---|
328 | #ifdef QT_MAC_USE_COCOA
|
---|
329 | /* Instantiate our NSApplication derivative before QApplication
|
---|
330 | * forces NSApplication to be instantiated. */
|
---|
331 | UICocoaApplication::instance();
|
---|
332 | #endif
|
---|
333 |
|
---|
334 | qInstallMsgHandler (QtMessageOutput);
|
---|
335 |
|
---|
336 | int rc = 1; /* failure */
|
---|
337 |
|
---|
338 | /* scope the QApplication variable */
|
---|
339 | {
|
---|
340 | #ifdef Q_WS_X11
|
---|
341 | /* Qt has a complex algorithm for selecting the right visual which
|
---|
342 | * doesn't always seem to work. So we naively choose a visual - the
|
---|
343 | * default one - ourselves and pass that to Qt. This means that we
|
---|
344 | * also have to open the display ourselves.
|
---|
345 | * We check the Qt parameter list and handle Qt's -display argument
|
---|
346 | * ourselves, since we open the display connection. We also check the
|
---|
347 | * to see if the user has passed Qt's -visual parameter, and if so we
|
---|
348 | * assume that the user wants Qt to handle visual selection after all,
|
---|
349 | * and don't supply a visual. */
|
---|
350 | char *pszDisplay = NULL;
|
---|
351 | bool useDefaultVisual = true;
|
---|
352 | for (int i = 0; i < argc; ++i)
|
---|
353 | {
|
---|
354 | if (!::strcmp(argv[i], "-display") && (i + 1 < argc))
|
---|
355 | /* What if it isn't? Rely on QApplication to complain? */
|
---|
356 | {
|
---|
357 | pszDisplay = argv[i + 1];
|
---|
358 | ++i;
|
---|
359 | }
|
---|
360 | else if (!::strcmp(argv[i], "-visual"))
|
---|
361 | useDefaultVisual = false;
|
---|
362 | }
|
---|
363 | Display *pDisplay = XOpenDisplay(pszDisplay);
|
---|
364 | if (!pDisplay)
|
---|
365 | {
|
---|
366 | RTPrintf(pszDisplay ? "Failed to open the X11 display \"%s\"!\n"
|
---|
367 | : "Failed to open the X11 display!\n",
|
---|
368 | pszDisplay);
|
---|
369 | return 0;
|
---|
370 | }
|
---|
371 | Visual *pVisual = useDefaultVisual
|
---|
372 | ? DefaultVisual(pDisplay, DefaultScreen(pDisplay))
|
---|
373 | : NULL;
|
---|
374 | /* Now create the application object */
|
---|
375 | QApplication a (pDisplay, argc, argv, (Qt::HANDLE) pVisual);
|
---|
376 | #else /* Q_WS_X11 */
|
---|
377 | QApplication a (argc, argv);
|
---|
378 | #endif /* Q_WS_X11 */
|
---|
379 |
|
---|
380 | /* Qt4.3 version has the QProcess bug which freezing the application
|
---|
381 | * for 30 seconds. This bug is internally used at initialization of
|
---|
382 | * Cleanlooks style. So we have to change this style to another one.
|
---|
383 | * See http://trolltech.com/developer/task-tracker/index_html?id=179200&method=entry
|
---|
384 | * for details. */
|
---|
385 | if (VBoxGlobal::qtRTVersionString().startsWith ("4.3") &&
|
---|
386 | qobject_cast <QCleanlooksStyle*> (QApplication::style()))
|
---|
387 | QApplication::setStyle (new QPlastiqueStyle);
|
---|
388 |
|
---|
389 | #ifdef Q_OS_SOLARIS
|
---|
390 | /* Use plastique look 'n feel for Solaris instead of the default motif (Qt 4.7.x) */
|
---|
391 | QApplication::setStyle (new QPlastiqueStyle);
|
---|
392 | #endif
|
---|
393 |
|
---|
394 | #ifdef Q_WS_X11
|
---|
395 | /* This patch is not used for now on Solaris & OpenSolaris because
|
---|
396 | * there is no anti-aliasing enabled by default, Qt4 to be rebuilt. */
|
---|
397 | #ifndef Q_OS_SOLARIS
|
---|
398 | /* Cause Qt4 has the conflict with fontconfig application as a result
|
---|
399 | * sometimes substituting some fonts with non scaleable-anti-aliased
|
---|
400 | * bitmap font we are reseting substitutes for the current application
|
---|
401 | * font family if it is non scaleable-anti-aliased. */
|
---|
402 | QFontDatabase fontDataBase;
|
---|
403 |
|
---|
404 | QString currentFamily (QApplication::font().family());
|
---|
405 | bool isCurrentScaleable = fontDataBase.isScalable (currentFamily);
|
---|
406 |
|
---|
407 | /*
|
---|
408 | LogFlowFunc (("Font: Current family is '%s'. It is %s.\n",
|
---|
409 | currentFamily.toLatin1().constData(),
|
---|
410 | isCurrentScaleable ? "scalable" : "not scalable"));
|
---|
411 | QStringList subFamilies (QFont::substitutes (currentFamily));
|
---|
412 | foreach (QString sub, subFamilies)
|
---|
413 | {
|
---|
414 | bool isSubScalable = fontDataBase.isScalable (sub);
|
---|
415 | LogFlowFunc (("Font: Substitute family is '%s'. It is %s.\n",
|
---|
416 | sub.toLatin1().constData(),
|
---|
417 | isSubScalable ? "scalable" : "not scalable"));
|
---|
418 | }
|
---|
419 | */
|
---|
420 |
|
---|
421 | QString subFamily (QFont::substitute (currentFamily));
|
---|
422 | bool isSubScaleable = fontDataBase.isScalable (subFamily);
|
---|
423 |
|
---|
424 | if (isCurrentScaleable && !isSubScaleable)
|
---|
425 | QFont::removeSubstitution (currentFamily);
|
---|
426 | #endif /* Q_OS_SOLARIS */
|
---|
427 | #endif
|
---|
428 |
|
---|
429 | #ifdef Q_WS_WIN
|
---|
430 | /* Drag in the sound drivers and DLLs early to get rid of the delay taking
|
---|
431 | * place when the main menu bar (or any action from that menu bar) is
|
---|
432 | * activated for the first time. This delay is especially annoying if it
|
---|
433 | * happens when the VM is executing in real mode (which gives 100% CPU
|
---|
434 | * load and slows down the load process that happens on the main GUI
|
---|
435 | * thread to several seconds). */
|
---|
436 | PlaySound (NULL, NULL, 0);
|
---|
437 | #endif
|
---|
438 |
|
---|
439 | #ifdef Q_WS_MAC
|
---|
440 | ::darwinDisableIconsInMenus();
|
---|
441 | #endif /* Q_WS_MAC */
|
---|
442 |
|
---|
443 | #ifdef Q_WS_X11
|
---|
444 | /* version check (major.minor are sensitive, fix number is ignored) */
|
---|
445 | if (VBoxGlobal::qtRTVersion() < (VBoxGlobal::qtCTVersion() & 0xFFFF00))
|
---|
446 | {
|
---|
447 | QString msg =
|
---|
448 | QApplication::tr ("Executable <b>%1</b> requires Qt %2.x, found Qt %3.")
|
---|
449 | .arg (qAppName())
|
---|
450 | .arg (VBoxGlobal::qtCTVersionString().section ('.', 0, 1))
|
---|
451 | .arg (VBoxGlobal::qtRTVersionString());
|
---|
452 | QMessageBox::critical (
|
---|
453 | 0, QApplication::tr ("Incompatible Qt Library Error"),
|
---|
454 | msg, QMessageBox::Abort, 0);
|
---|
455 | qFatal ("%s", msg.toAscii().constData());
|
---|
456 | }
|
---|
457 | #endif
|
---|
458 |
|
---|
459 | /* load a translation based on the current locale */
|
---|
460 | VBoxGlobal::loadLanguage();
|
---|
461 |
|
---|
462 | do
|
---|
463 | {
|
---|
464 | if (!vboxGlobal().isValid())
|
---|
465 | break;
|
---|
466 |
|
---|
467 |
|
---|
468 | if (vboxGlobal().processArgs())
|
---|
469 | return 0;
|
---|
470 |
|
---|
471 | msgCenter().checkForMountedWrongUSB();
|
---|
472 |
|
---|
473 | VBoxGlobalSettings settings = vboxGlobal().settings();
|
---|
474 | /* Process known keys */
|
---|
475 | bool noSelector = settings.isFeatureActive ("noSelector");
|
---|
476 |
|
---|
477 | if (vboxGlobal().isVMConsoleProcess())
|
---|
478 | {
|
---|
479 | #ifdef VBOX_GUI_WITH_SYSTRAY
|
---|
480 | if (vboxGlobal().trayIconInstall())
|
---|
481 | {
|
---|
482 | /* Nothing to do here yet. */
|
---|
483 | }
|
---|
484 | #endif
|
---|
485 | if (vboxGlobal().startMachine (vboxGlobal().managedVMUuid()))
|
---|
486 | {
|
---|
487 | vboxGlobal().setMainWindow (vboxGlobal().vmWindow());
|
---|
488 | rc = a.exec();
|
---|
489 | }
|
---|
490 | }
|
---|
491 | else if (noSelector)
|
---|
492 | {
|
---|
493 | msgCenter().cannotRunInSelectorMode();
|
---|
494 | }
|
---|
495 | else
|
---|
496 | {
|
---|
497 | #ifdef VBOX_BLEEDING_EDGE
|
---|
498 | msgCenter().showBEBWarning();
|
---|
499 | #else
|
---|
500 | # ifndef DEBUG
|
---|
501 | /* Check for BETA version */
|
---|
502 | QString vboxVersion (vboxGlobal().virtualBox().GetVersion());
|
---|
503 | if (vboxVersion.contains ("BETA"))
|
---|
504 | {
|
---|
505 | /* Allow to prevent this message */
|
---|
506 | QString str = vboxGlobal().virtualBox().
|
---|
507 | GetExtraData(GUI_PreventBetaWarning);
|
---|
508 | if (str != vboxVersion)
|
---|
509 | msgCenter().showBETAWarning();
|
---|
510 | }
|
---|
511 | # endif
|
---|
512 | #endif
|
---|
513 |
|
---|
514 | vboxGlobal().setMainWindow (&vboxGlobal().selectorWnd());
|
---|
515 | #ifdef VBOX_GUI_WITH_SYSTRAY
|
---|
516 | if (vboxGlobal().trayIconInstall())
|
---|
517 | {
|
---|
518 | /* Nothing to do here yet. */
|
---|
519 | }
|
---|
520 |
|
---|
521 | if (false == vboxGlobal().isTrayMenu())
|
---|
522 | {
|
---|
523 | #endif
|
---|
524 | vboxGlobal().selectorWnd().show();
|
---|
525 | #ifdef VBOX_WITH_REGISTRATION_REQUEST
|
---|
526 | vboxGlobal().showRegistrationDialog (false /* aForce */);
|
---|
527 | #endif
|
---|
528 | #ifdef VBOX_GUI_WITH_SYSTRAY
|
---|
529 | }
|
---|
530 |
|
---|
531 | do
|
---|
532 | {
|
---|
533 | #endif
|
---|
534 | rc = a.exec();
|
---|
535 | #ifdef VBOX_GUI_WITH_SYSTRAY
|
---|
536 | } while (vboxGlobal().isTrayMenu());
|
---|
537 | #endif
|
---|
538 | }
|
---|
539 | }
|
---|
540 | while (0);
|
---|
541 | }
|
---|
542 |
|
---|
543 | LogFlowFunc (("rc=%d\n", rc));
|
---|
544 | LogFlowFuncLeave();
|
---|
545 |
|
---|
546 | return rc;
|
---|
547 | }
|
---|
548 |
|
---|
549 | #ifndef VBOX_WITH_HARDENING
|
---|
550 |
|
---|
551 | int main (int argc, char **argv, char **envp)
|
---|
552 | {
|
---|
553 | /* Initialize VBox Runtime. Initialize the SUPLib as well only if we
|
---|
554 | * are really about to start a VM. Don't do this if we are only starting
|
---|
555 | * the selector window. */
|
---|
556 | bool fInitSUPLib = false;
|
---|
557 | for (int i = 1; i < argc; i++)
|
---|
558 | {
|
---|
559 | /* NOTE: the check here must match the corresponding check for the
|
---|
560 | * options to start a VM in hardenedmain.cpp and VBoxGlobal.cpp exactly,
|
---|
561 | * otherwise there will be weird error messages. */
|
---|
562 | if ( !::strcmp(argv[i], "--startvm")
|
---|
563 | || !::strcmp(argv[i], "-startvm"))
|
---|
564 | {
|
---|
565 | fInitSUPLib = true;
|
---|
566 | break;
|
---|
567 | }
|
---|
568 | }
|
---|
569 |
|
---|
570 | int rc = RTR3InitExe(argc, &argv, fInitSUPLib ? RTR3INIT_FLAGS_SUPLIB : 0);
|
---|
571 | if (RT_FAILURE(rc))
|
---|
572 | {
|
---|
573 | QApplication a (argc, &argv[0]);
|
---|
574 | #ifdef Q_OS_SOLARIS
|
---|
575 | /* Use plastique look 'n feel for Solaris instead of the default motif (Qt 4.7.x) */
|
---|
576 | QApplication::setStyle (new QPlastiqueStyle);
|
---|
577 | #endif
|
---|
578 | QString msgTitle = QApplication::tr ("VirtualBox - Runtime Error");
|
---|
579 | QString msgText = "<html>";
|
---|
580 |
|
---|
581 | switch (rc)
|
---|
582 | {
|
---|
583 | case VERR_VM_DRIVER_NOT_INSTALLED:
|
---|
584 | case VERR_VM_DRIVER_LOAD_ERROR:
|
---|
585 | msgText += QApplication::tr (
|
---|
586 | "<b>Cannot access the kernel driver!</b><br/><br/>");
|
---|
587 | # ifdef RT_OS_LINUX
|
---|
588 | msgText += g_QStrHintLinuxNoDriver;
|
---|
589 | # else
|
---|
590 | msgText += g_QStrHintOtherNoDriver;
|
---|
591 | # endif
|
---|
592 | break;
|
---|
593 | # ifdef RT_OS_LINUX
|
---|
594 | case VERR_NO_MEMORY:
|
---|
595 | msgText += g_QStrHintLinuxNoMemory;
|
---|
596 | break;
|
---|
597 | # endif
|
---|
598 | case VERR_VM_DRIVER_NOT_ACCESSIBLE:
|
---|
599 | msgText += QApplication::tr ("Kernel driver not accessible");
|
---|
600 | break;
|
---|
601 | case VERR_VM_DRIVER_VERSION_MISMATCH:
|
---|
602 | # ifdef RT_OS_LINUX
|
---|
603 | msgText += g_QStrHintLinuxWrongDriverVersion;
|
---|
604 | # else
|
---|
605 | msgText += g_QStrHintOtherWrongDriverVersion;
|
---|
606 | # endif
|
---|
607 | break;
|
---|
608 | default:
|
---|
609 | msgText += QApplication::tr (
|
---|
610 | "Unknown error %2 during initialization of the Runtime"
|
---|
611 | ).arg (rc);
|
---|
612 | break;
|
---|
613 | }
|
---|
614 | msgText += "</html>";
|
---|
615 | QMessageBox::critical (
|
---|
616 | 0, /* parent */
|
---|
617 | msgTitle,
|
---|
618 | msgText,
|
---|
619 | QMessageBox::Abort, /* button0 */
|
---|
620 | 0); /* button1 */
|
---|
621 | return 1;
|
---|
622 | }
|
---|
623 |
|
---|
624 | return TrustedMain (argc, argv, envp);
|
---|
625 | }
|
---|
626 |
|
---|
627 | #else /* VBOX_WITH_HARDENING */
|
---|
628 |
|
---|
629 | /**
|
---|
630 | * Hardened main failed, report the error without any unnecessary fuzz.
|
---|
631 | *
|
---|
632 | * @remarks Do not call IPRT here unless really required, it might not be
|
---|
633 | * initialized.
|
---|
634 | */
|
---|
635 | extern "C" DECLEXPORT(void) TrustedError (const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, va_list va)
|
---|
636 | {
|
---|
637 | # if defined(RT_OS_DARWIN)
|
---|
638 | ShutUpAppKit();
|
---|
639 | # endif
|
---|
640 |
|
---|
641 | /*
|
---|
642 | * Init the Qt application object. This is a bit hackish as we
|
---|
643 | * don't have the argument vector handy.
|
---|
644 | */
|
---|
645 | int argc = 0;
|
---|
646 | char *argv[2] = { NULL, NULL };
|
---|
647 | QApplication a (argc, &argv[0]);
|
---|
648 |
|
---|
649 | /*
|
---|
650 | * Compose and show the error message.
|
---|
651 | */
|
---|
652 | QString msgTitle = QApplication::tr ("VirtualBox - Error In %1").arg (pszWhere);
|
---|
653 |
|
---|
654 | char msgBuf[1024];
|
---|
655 | vsprintf (msgBuf, pszMsgFmt, va);
|
---|
656 |
|
---|
657 | QString msgText = QApplication::tr (
|
---|
658 | "<html><b>%1 (rc=%2)</b><br/><br/>").arg (msgBuf).arg (rc);
|
---|
659 | switch (enmWhat)
|
---|
660 | {
|
---|
661 | case kSupInitOp_Driver:
|
---|
662 | # ifdef RT_OS_LINUX
|
---|
663 | msgText += g_QStrHintLinuxNoDriver;
|
---|
664 | # else
|
---|
665 | msgText += g_QStrHintOtherNoDriver;
|
---|
666 | # endif
|
---|
667 | break;
|
---|
668 | # ifdef RT_OS_LINUX
|
---|
669 | case kSupInitOp_IPRT:
|
---|
670 | if (rc == VERR_NO_MEMORY)
|
---|
671 | msgText += g_QStrHintLinuxNoMemory;
|
---|
672 | else
|
---|
673 | # endif
|
---|
674 | if (rc == VERR_VM_DRIVER_VERSION_MISMATCH)
|
---|
675 | # ifdef RT_OS_LINUX
|
---|
676 | msgText += g_QStrHintLinuxWrongDriverVersion;
|
---|
677 | # else
|
---|
678 | msgText += g_QStrHintOtherWrongDriverVersion;
|
---|
679 | # endif
|
---|
680 | else
|
---|
681 | msgText += g_QStrHintReinstall;
|
---|
682 | break;
|
---|
683 | case kSupInitOp_Integrity:
|
---|
684 | case kSupInitOp_RootCheck:
|
---|
685 | msgText += g_QStrHintReinstall;
|
---|
686 | break;
|
---|
687 | default:
|
---|
688 | /* no hints here */
|
---|
689 | break;
|
---|
690 | }
|
---|
691 | msgText += "</html>";
|
---|
692 |
|
---|
693 | # ifdef RT_OS_LINUX
|
---|
694 | sleep(2);
|
---|
695 | # endif
|
---|
696 | QMessageBox::critical (
|
---|
697 | 0, /* parent */
|
---|
698 | msgTitle, /* title */
|
---|
699 | msgText, /* text */
|
---|
700 | QMessageBox::Abort, /* button0 */
|
---|
701 | 0); /* button1 */
|
---|
702 | qFatal ("%s", msgText.toAscii().constData());
|
---|
703 | }
|
---|
704 |
|
---|
705 | #endif /* VBOX_WITH_HARDENING */
|
---|
706 |
|
---|