VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/init.cpp@ 60370

Last change on this file since 60370 was 59404, checked in by vboxsync, 9 years ago

Forward-ported r104938, r104943, r104950, r104952, r104953, r104987, r104988, r104990 from 5.0:

  • VBoxStub: Lazy import DLLs not in the KnownDlls list (and then some) and check that we don't accidentally add new imports as time goes by.
  • VBoxStub: the dlls have export names, so use them instead of the ordinals.
  • VBoxDef2LazyLoad fixes and error reporting, fixed missing VBoxCheckImports dependency during use in VBoxStub.
  • iprt/initterm.h,vbox-img,VBoxStub: Introduced RTR3INIT_FLAGS_STANDALONE_APP for statically linked applications that are expected to run outside the normal VirtualBox installation directory and need to be on their toes wrt dynamic library search paths. (Only windows, really.) Also, _always_ initialize IPRT first, don't ever do anything before that unless it 104% must be done there.
  • RTR3INIT_FLAGS_STANDALONE_APP trumps concerns about Vista GUI
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 20.2 KB
Line 
1/* $Id: init.cpp 59404 2016-01-19 10:10:39Z vboxsync $ */
2/** @file
3 * IPRT - Init Ring-3.
4 */
5
6/*
7 * Copyright (C) 2006-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DEFAULT
32#include <iprt/types.h> /* darwin: UINT32_C and others. */
33
34#ifdef RT_OS_WINDOWS
35# include <process.h>
36# include <Windows.h>
37#else
38# include <unistd.h>
39# ifndef RT_OS_OS2
40# include <pthread.h>
41# include <signal.h>
42# include <errno.h>
43# define IPRT_USE_SIG_CHILD_DUMMY
44# endif
45#endif
46#ifdef RT_OS_OS2
47# include <InnoTekLIBC/fork.h>
48# define INCL_DOSMISC
49# include <os2.h>
50#endif
51#include <locale.h>
52
53#include <iprt/initterm.h>
54#include <iprt/asm.h>
55#include <iprt/assert.h>
56#include <iprt/err.h>
57#include <iprt/log.h>
58#include <iprt/mem.h>
59#include <iprt/path.h>
60#include <iprt/time.h>
61#include <iprt/string.h>
62#include <iprt/param.h>
63#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
64# include <iprt/file.h>
65# include <VBox/sup.h>
66#endif
67#include <stdlib.h>
68
69#include "init.h"
70#include "internal/alignmentchecks.h"
71#include "internal/path.h"
72#include "internal/process.h"
73#include "internal/thread.h"
74#include "internal/time.h"
75
76
77/*********************************************************************************************************************************
78* Global Variables *
79*********************************************************************************************************************************/
80/** The number of calls to RTR3Init*. */
81static int32_t volatile g_cUsers = 0;
82/** Whether we're currently initializing the IPRT. */
83static bool volatile g_fInitializing = false;
84
85/** The process path.
86 * This is used by RTPathExecDir and RTProcGetExecutablePath and set by rtProcInitName. */
87DECLHIDDEN(char) g_szrtProcExePath[RTPATH_MAX];
88/** The length of g_szrtProcExePath. */
89DECLHIDDEN(size_t) g_cchrtProcExePath;
90/** The length of directory path component of g_szrtProcExePath. */
91DECLHIDDEN(size_t) g_cchrtProcDir;
92/** The offset of the process name into g_szrtProcExePath. */
93DECLHIDDEN(size_t) g_offrtProcName;
94
95/** The IPRT init flags. */
96static uint32_t g_fInitFlags;
97
98/** The argument count of the program. */
99static int g_crtArgs = -1;
100/** The arguments of the program (UTF-8). This is "leaked". */
101static char ** g_papszrtArgs;
102/** The original argument vector of the program. */
103static char ** g_papszrtOrgArgs;
104
105/**
106 * Program start nanosecond TS.
107 */
108DECLHIDDEN(uint64_t) g_u64ProgramStartNanoTS;
109
110/**
111 * Program start microsecond TS.
112 */
113DECLHIDDEN(uint64_t) g_u64ProgramStartMicroTS;
114
115/**
116 * Program start millisecond TS.
117 */
118DECLHIDDEN(uint64_t) g_u64ProgramStartMilliTS;
119
120/**
121 * The process identifier of the running process.
122 */
123DECLHIDDEN(RTPROCESS) g_ProcessSelf = NIL_RTPROCESS;
124
125/**
126 * The current process priority.
127 */
128DECLHIDDEN(RTPROCPRIORITY) g_enmProcessPriority = RTPROCPRIORITY_DEFAULT;
129
130/**
131 * Set if the atexit callback has been called, i.e. indicating
132 * that the process is terminating.
133 */
134DECLHIDDEN(bool volatile) g_frtAtExitCalled = false;
135
136#ifdef IPRT_WITH_ALIGNMENT_CHECKS
137/**
138 * Whether alignment checks are enabled.
139 * This is set if the environment variable IPRT_ALIGNMENT_CHECKS is 1.
140 */
141RTDATADECL(bool) g_fRTAlignmentChecks = false;
142#endif
143
144
145#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_HAIKU) \
146 || defined(RT_OS_LINUX) || defined(RT_OS_OS2) || defined(RT_OS_SOLARIS) /** @todo add host init hooks everywhere. */
147/* Stubs */
148DECLHIDDEN(int) rtR3InitNativeFirst(uint32_t fFlags) { return VINF_SUCCESS; }
149DECLHIDDEN(int) rtR3InitNativeFinal(uint32_t fFlags) { return VINF_SUCCESS; }
150DECLHIDDEN(void) rtR3InitNativeObtrusive(uint32_t fFlags) { }
151#endif
152
153
154/**
155 * atexit callback.
156 *
157 * This makes sure any loggers are flushed and will later also work the
158 * termination callback chain.
159 */
160static void rtR3ExitCallback(void)
161{
162 ASMAtomicWriteBool(&g_frtAtExitCalled, true);
163
164 if (g_cUsers > 0)
165 {
166 PRTLOGGER pLogger = RTLogGetDefaultInstance();
167 if (pLogger)
168 RTLogFlush(pLogger);
169
170 pLogger = RTLogRelGetDefaultInstance();
171 if (pLogger)
172 RTLogFlush(pLogger);
173 }
174}
175
176
177#ifndef RT_OS_WINDOWS
178/**
179 * Fork callback, child context.
180 */
181static void rtR3ForkChildCallback(void)
182{
183 g_ProcessSelf = getpid();
184}
185#endif /* RT_OS_WINDOWS */
186
187#ifdef RT_OS_OS2
188/** Fork completion callback for OS/2. Only called in the child. */
189static void rtR3ForkOs2ChildCompletionCallback(void *pvArg, int rc, __LIBC_FORKCTX enmCtx)
190{
191 Assert(enmCtx == __LIBC_FORK_CTX_CHILD); NOREF(enmCtx);
192 NOREF(pvArg);
193
194 if (!rc)
195 rtR3ForkChildCallback();
196}
197
198/** Low-level fork callback for OS/2. */
199int rtR3ForkOs2Child(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation)
200{
201 if (enmOperation == __LIBC_FORK_OP_EXEC_CHILD)
202 return pForkHandle->pfnCompletionCallback(pForkHandle, rtR3ForkOs2ChildCompletionCallback, NULL, __LIBC_FORK_CTX_CHILD);
203 return 0;
204}
205
206# define static static volatile /** @todo _FORK_CHILD1 causes unresolved externals in optimized builds. Fix macro. */
207_FORK_CHILD1(0, rtR3ForkOs2Child);
208# undef static
209#endif /* RT_OS_OS2 */
210
211
212
213/**
214 * Internal worker which initializes or re-initializes the
215 * program path, name and directory globals.
216 *
217 * @returns IPRT status code.
218 * @param pszProgramPath The program path, NULL if not specified.
219 */
220static int rtR3InitProgramPath(const char *pszProgramPath)
221{
222 /*
223 * We're reserving 32 bytes here for file names as what not.
224 */
225 if (!pszProgramPath)
226 {
227 int rc = rtProcInitExePath(g_szrtProcExePath, sizeof(g_szrtProcExePath) - 32);
228 if (RT_FAILURE(rc))
229 return rc;
230 }
231 else
232 {
233 size_t cch = strlen(pszProgramPath);
234 Assert(cch > 1);
235 AssertMsgReturn(cch < sizeof(g_szrtProcExePath) - 32, ("%zu\n", cch), VERR_BUFFER_OVERFLOW);
236 memcpy(g_szrtProcExePath, pszProgramPath, cch + 1);
237 }
238
239 /*
240 * Parse the name.
241 */
242 ssize_t offName;
243 g_cchrtProcExePath = RTPathParseSimple(g_szrtProcExePath, &g_cchrtProcDir, &offName, NULL);
244 g_offrtProcName = offName;
245 return VINF_SUCCESS;
246}
247
248
249/**
250 * Internal worker which initializes or re-initializes the
251 * program path, name and directory globals.
252 *
253 * @returns IPRT status code.
254 * @param fFlags Flags, see RTR3INIT_XXX.
255 * @param cArgs Pointer to the argument count.
256 * @param ppapszArgs Pointer to the argument vector pointer. NULL
257 * allowed if @a cArgs is 0.
258 */
259static int rtR3InitArgv(uint32_t fFlags, int cArgs, char ***ppapszArgs)
260{
261 NOREF(fFlags);
262 if (cArgs)
263 {
264 AssertPtr(ppapszArgs);
265 AssertPtr(*ppapszArgs);
266 char **papszOrgArgs = *ppapszArgs;
267
268 /*
269 * Normally we should only be asked to convert arguments once. If we
270 * are though, it should be the already convered arguments.
271 */
272 if (g_crtArgs != -1)
273 {
274 AssertReturn( g_crtArgs == cArgs
275 && g_papszrtArgs == papszOrgArgs,
276 VERR_WRONG_ORDER); /* only init once! */
277 return VINF_SUCCESS;
278 }
279
280 if (!(fFlags & RTR3INIT_FLAGS_UTF8_ARGV))
281 {
282 /*
283 * Convert the arguments.
284 */
285 char **papszArgs = (char **)RTMemAllocZ((cArgs + 1) * sizeof(char *));
286 if (!papszArgs)
287 return VERR_NO_MEMORY;
288
289#ifdef RT_OS_WINDOWS
290 /* HACK ALERT! Try convert from unicode versions if possible.
291 Unfortunately for us, __wargv is only initialized if we have a
292 unicode main function. So, we have to use CommandLineToArgvW to get
293 something similar. It should do the same conversion... :-) */
294 int cArgsW = -1;
295 PWSTR *papwszArgs = NULL;
296 if ( papszOrgArgs == __argv
297 && cArgs == __argc
298 && (papwszArgs = CommandLineToArgvW(GetCommandLineW(), &cArgsW)) != NULL )
299 {
300 AssertMsg(cArgsW == cArgs, ("%d vs %d\n", cArgsW, cArgs));
301 for (int i = 0; i < cArgs; i++)
302 {
303 int rc = RTUtf16ToUtf8(papwszArgs[i], &papszArgs[i]);
304 if (RT_FAILURE(rc))
305 {
306 while (i--)
307 RTStrFree(papszArgs[i]);
308 RTMemFree(papszArgs);
309 LocalFree(papwszArgs);
310 return rc;
311 }
312 }
313 LocalFree(papwszArgs);
314 }
315 else
316#endif
317 {
318 for (int i = 0; i < cArgs; i++)
319 {
320 int rc = RTStrCurrentCPToUtf8(&papszArgs[i], papszOrgArgs[i]);
321 if (RT_FAILURE(rc))
322 {
323 while (i--)
324 RTStrFree(papszArgs[i]);
325 RTMemFree(papszArgs);
326 return rc;
327 }
328 }
329 }
330
331 papszArgs[cArgs] = NULL;
332
333 g_papszrtOrgArgs = papszOrgArgs;
334 g_papszrtArgs = papszArgs;
335 g_crtArgs = cArgs;
336
337 *ppapszArgs = papszArgs;
338 }
339 else
340 {
341 /*
342 * The arguments are already UTF-8, no conversion needed.
343 */
344 g_papszrtOrgArgs = papszOrgArgs;
345 g_papszrtArgs = papszOrgArgs;
346 g_crtArgs = cArgs;
347 }
348 }
349
350 return VINF_SUCCESS;
351}
352
353
354#ifdef IPRT_USE_SIG_CHILD_DUMMY
355/**
356 * Dummy SIGCHILD handler.
357 *
358 * Assigned on rtR3Init only when SIGCHILD handler is set SIGIGN or SIGDEF to
359 * ensure waitpid works properly for the terminated processes.
360 */
361static void rtR3SigChildHandler(int iSignal)
362{
363 NOREF(iSignal);
364}
365#endif /* IPRT_USE_SIG_CHILD_DUMMY */
366
367
368/**
369 * rtR3Init worker.
370 */
371static int rtR3InitBody(uint32_t fFlags, int cArgs, char ***ppapszArgs, const char *pszProgramPath)
372{
373 /*
374 * Early native initialization.
375 */
376 int rc = rtR3InitNativeFirst(fFlags);
377 AssertMsgRCReturn(rc, ("rtR3InitNativeFirst failed with %Rrc\n", rc), rc);
378
379 /*
380 * Disable error popups.
381 */
382#if defined(RT_OS_OS2) /** @todo move to private code. */
383 DosError(FERR_DISABLEHARDERR);
384#endif
385
386 /*
387 * Init C runtime locale before we do anything that may end up converting
388 * paths or we'll end up using the "C" locale for path conversion.
389 */
390 setlocale(LC_CTYPE, "");
391
392 /*
393 * The Process ID.
394 */
395#ifdef _MSC_VER
396 g_ProcessSelf = _getpid(); /* crappy ansi compiler */
397#else
398 g_ProcessSelf = getpid();
399#endif
400
401 /*
402 * Save the init flags.
403 */
404 g_fInitFlags |= fFlags;
405
406#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
407# ifdef VBOX
408 /*
409 * This MUST be done as the very first thing, before any file is opened.
410 * The log is opened on demand, but the first log entries may be caused
411 * by rtThreadInit() below.
412 */
413 const char *pszDisableHostCache = getenv("VBOX_DISABLE_HOST_DISK_CACHE");
414 if ( pszDisableHostCache != NULL
415 && *pszDisableHostCache
416 && strcmp(pszDisableHostCache, "0") != 0)
417 {
418 RTFileSetForceFlags(RTFILE_O_WRITE, RTFILE_O_WRITE_THROUGH, 0);
419 RTFileSetForceFlags(RTFILE_O_READWRITE, RTFILE_O_WRITE_THROUGH, 0);
420 }
421# endif /* VBOX */
422#endif /* !IN_GUEST && !RT_NO_GIP */
423
424 /*
425 * Thread Thread database and adopt the caller thread as 'main'.
426 * This must be done before everything else or else we'll call into threading
427 * without having initialized TLS entries and suchlike.
428 */
429 rc = rtThreadInit();
430 AssertMsgRCReturn(rc, ("Failed to initialize threads, rc=%Rrc!\n", rc), rc);
431
432#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
433 if (fFlags & RTR3INIT_FLAGS_SUPLIB)
434 {
435 /*
436 * Init GIP first.
437 * (The more time for updates before real use, the better.)
438 */
439 rc = SUPR3Init(NULL);
440 AssertMsgRCReturn(rc, ("Failed to initializable the support library, rc=%Rrc!\n", rc), rc);
441 }
442#endif
443
444 /*
445 * The executable path, name and directory. Convert arguments.
446 */
447 rc = rtR3InitProgramPath(pszProgramPath);
448 AssertLogRelMsgRCReturn(rc, ("Failed to get executable directory path, rc=%Rrc!\n", rc), rc);
449
450 rc = rtR3InitArgv(fFlags, cArgs, ppapszArgs);
451 AssertLogRelMsgRCReturn(rc, ("Failed to convert the arguments, rc=%Rrc!\n", rc), rc);
452
453#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
454 /*
455 * The threading is initialized we can safely sleep a bit if GIP
456 * needs some time to update itself updating.
457 */
458 if ((fFlags & RTR3INIT_FLAGS_SUPLIB) && g_pSUPGlobalInfoPage)
459 {
460 RTThreadSleep(20);
461 RTTimeNanoTS();
462 }
463#endif
464
465 /*
466 * Init the program start TSes.
467 * Do that here to be sure that the GIP time was properly updated the 1st time.
468 */
469 g_u64ProgramStartNanoTS = RTTimeNanoTS();
470 g_u64ProgramStartMicroTS = g_u64ProgramStartNanoTS / 1000;
471 g_u64ProgramStartMilliTS = g_u64ProgramStartNanoTS / 1000000;
472
473 /*
474 * The remainder cannot easily be undone, so it has to go last.
475 */
476
477 /* Fork and exit callbacks. */
478#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
479 rc = pthread_atfork(NULL, NULL, rtR3ForkChildCallback);
480 AssertMsg(rc == 0, ("%d\n", rc));
481#endif
482 atexit(rtR3ExitCallback);
483
484#ifdef IPRT_USE_SIG_CHILD_DUMMY
485 /*
486 * SIGCHLD must not be ignored (that's default), otherwise posix compliant waitpid
487 * implementations won't work right.
488 */
489 for (;;)
490 {
491 struct sigaction saOld;
492 rc = sigaction(SIGCHLD, 0, &saOld); AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
493 if ( rc != 0
494 || (saOld.sa_flags & SA_SIGINFO)
495 || ( saOld.sa_handler != SIG_IGN
496 && saOld.sa_handler != SIG_DFL)
497 )
498 break;
499
500 /* Try install dummy handler. */
501 struct sigaction saNew = saOld;
502 saNew.sa_flags = SA_NOCLDSTOP | SA_RESTART;
503 saNew.sa_handler = rtR3SigChildHandler;
504 rc = sigemptyset(&saNew.sa_mask); AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
505 struct sigaction saOld2;
506 rc = sigaction(SIGCHLD, &saNew, &saOld2); AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
507 if ( rc != 0
508 || ( saOld2.sa_handler == saOld.sa_handler
509 && !(saOld2.sa_flags & SA_SIGINFO))
510 )
511 break;
512
513 /* Race during dynamic load, restore and try again... */
514 sigaction(SIGCHLD, &saOld2, NULL);
515 RTThreadYield();
516 }
517#endif /* IPRT_USE_SIG_CHILD_DUMMY */
518
519#ifdef IPRT_WITH_ALIGNMENT_CHECKS
520 /*
521 * Enable alignment checks.
522 */
523 const char *pszAlignmentChecks = getenv("IPRT_ALIGNMENT_CHECKS");
524 g_fRTAlignmentChecks = pszAlignmentChecks != NULL
525 && pszAlignmentChecks[0] == '1'
526 && pszAlignmentChecks[1] == '\0';
527 if (g_fRTAlignmentChecks)
528 IPRT_ALIGNMENT_CHECKS_ENABLE();
529#endif
530
531 /*
532 * Final native initialization.
533 */
534 rc = rtR3InitNativeFinal(fFlags);
535 AssertMsgRCReturn(rc, ("rtR3InitNativeFinal failed with %Rrc\n", rc), rc);
536
537 return VINF_SUCCESS;
538}
539
540
541/**
542 * Internal initialization worker.
543 *
544 * @returns IPRT status code.
545 * @param fFlags Flags, see RTR3INIT_XXX.
546 * @param cArgs Pointer to the argument count.
547 * @param ppapszArgs Pointer to the argument vector pointer. NULL
548 * allowed if @a cArgs is 0.
549 * @param pszProgramPath The program path. Pass NULL if we're to figure it
550 * out ourselves.
551 */
552static int rtR3Init(uint32_t fFlags, int cArgs, char ***ppapszArgs, const char *pszProgramPath)
553{
554 /* no entry log flow, because prefixes and thread may freak out. */
555 Assert(!(fFlags & ~( RTR3INIT_FLAGS_DLL
556 | RTR3INIT_FLAGS_SUPLIB
557 | RTR3INIT_FLAGS_UNOBTRUSIVE
558 | RTR3INIT_FLAGS_UTF8_ARGV
559 | RTR3INIT_FLAGS_STANDALONE_APP)));
560 Assert(!(fFlags & RTR3INIT_FLAGS_DLL) || cArgs == 0);
561
562 /*
563 * Do reference counting, only initialize the first time around.
564 *
565 * We are ASSUMING that nobody will be able to race RTR3Init* calls when the
566 * first one, the real init, is running (second assertion).
567 */
568 int32_t cUsers = ASMAtomicIncS32(&g_cUsers);
569 if (cUsers != 1)
570 {
571 AssertMsg(cUsers > 1, ("%d\n", cUsers));
572 Assert(!g_fInitializing);
573#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
574 if (fFlags & RTR3INIT_FLAGS_SUPLIB)
575 {
576 SUPR3Init(NULL);
577 g_fInitFlags |= RTR3INIT_FLAGS_SUPLIB;
578 }
579#endif
580 g_fInitFlags |= fFlags & RTR3INIT_FLAGS_UTF8_ARGV;
581
582 if ( !(fFlags & RTR3INIT_FLAGS_UNOBTRUSIVE)
583 && (g_fInitFlags & RTR3INIT_FLAGS_UNOBTRUSIVE))
584 {
585 g_fInitFlags &= ~RTR3INIT_FLAGS_UNOBTRUSIVE;
586 g_fInitFlags |= fFlags & RTR3INIT_FLAGS_STANDALONE_APP;
587 rtR3InitNativeObtrusive(g_fInitFlags | fFlags);
588 rtThreadReInitObtrusive();
589 }
590 else
591 Assert(!(fFlags & RTR3INIT_FLAGS_STANDALONE_APP) || (g_fInitFlags & RTR3INIT_FLAGS_STANDALONE_APP));
592
593 int rc = VINF_SUCCESS;
594 if (pszProgramPath)
595 rc = rtR3InitProgramPath(pszProgramPath);
596 if (RT_SUCCESS(rc))
597 rc = rtR3InitArgv(fFlags, cArgs, ppapszArgs);
598 return rc;
599 }
600 ASMAtomicWriteBool(&g_fInitializing, true);
601
602 /*
603 * Do the initialization.
604 */
605 int rc = rtR3InitBody(fFlags, cArgs, ppapszArgs, pszProgramPath);
606 if (RT_FAILURE(rc))
607 {
608 /* failure */
609 ASMAtomicWriteBool(&g_fInitializing, false);
610 ASMAtomicDecS32(&g_cUsers);
611 return rc;
612 }
613
614 /* success */
615 LogFlow(("rtR3Init: returns VINF_SUCCESS\n"));
616 ASMAtomicWriteBool(&g_fInitializing, false);
617 return VINF_SUCCESS;
618}
619
620
621RTR3DECL(int) RTR3InitExe(int cArgs, char ***ppapszArgs, uint32_t fFlags)
622{
623 Assert(!(fFlags & RTR3INIT_FLAGS_DLL));
624 return rtR3Init(fFlags, cArgs, ppapszArgs, NULL);
625}
626
627
628RTR3DECL(int) RTR3InitExeNoArguments(uint32_t fFlags)
629{
630 Assert(!(fFlags & RTR3INIT_FLAGS_DLL));
631 return rtR3Init(fFlags, 0, NULL, NULL);
632}
633
634
635RTR3DECL(int) RTR3InitDll(uint32_t fFlags)
636{
637 Assert(!(fFlags & RTR3INIT_FLAGS_DLL));
638 return rtR3Init(fFlags | RTR3INIT_FLAGS_DLL, 0, NULL, NULL);
639}
640
641
642RTR3DECL(int) RTR3InitEx(uint32_t iVersion, uint32_t fFlags, int cArgs, char ***ppapszArgs, const char *pszProgramPath)
643{
644 AssertReturn(iVersion == RTR3INIT_VER_CUR, VERR_NOT_SUPPORTED);
645 return rtR3Init(fFlags, cArgs, ppapszArgs, pszProgramPath);
646}
647
648
649RTR3DECL(bool) RTR3InitIsInitialized(void)
650{
651 return g_cUsers >= 1 && !g_fInitializing;
652}
653
654
655RTR3DECL(bool) RTR3InitIsUnobtrusive(void)
656{
657 return RT_BOOL(g_fInitFlags & RTR3INIT_FLAGS_UNOBTRUSIVE);
658}
659
660
661#if 0 /** @todo implement RTR3Term. */
662RTR3DECL(void) RTR3Term(void)
663{
664}
665#endif
666
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette