initterm.cpp revision 8bc83e5cee630bad71985c8ddf175f6eab0bfb7a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/* $Id$ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** @file
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * MS COM / XPCOM Abstraction Layer - Initialization and Termination.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * available from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * General Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * additional information or have any questions.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if !defined (VBOX_WITH_XPCOM)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <objbase.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#else /* !defined (VBOX_WITH_XPCOM) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <stdlib.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/* XPCOM_GLUE is defined when the client uses the standalone glue
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync * (i.e. dynamically picks up the existing XPCOM shared library installation).
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync * This is not the case for VirtualBox XPCOM clients (they are always
1859e17ebfeca9bb36190ecf145a6d023eae00b4vboxsync * distrubuted with the self-built XPCOM library, and therefore have a binary
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * dependency on it) but left here for clarity.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined (XPCOM_GLUE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsXPCOMGlue.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsIComponentRegistrar.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsIServiceManager.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsCOMPtr.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsEventQueueUtils.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsEmbedString.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsILocalFile.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsIDirectoryService.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <nsDirectoryServiceDefs.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif /* !defined (VBOX_WITH_XPCOM) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include "VBox/com/com.h"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include "VBox/com/assert.h"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include "VBox/com/EventQueue.h"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include "../include/Logging.h"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/asm.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/env.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/param.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/path.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/string.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/thread.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <VBox/err.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncnamespace com
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined (VBOX_WITH_XPCOM)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsyncclass DirectoryServiceProvider : public nsIDirectoryServiceProvider
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsyncpublic:
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync NS_DECL_ISUPPORTS
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync DirectoryServiceProvider()
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync : mCompRegLocation (NULL), mXPTIDatLocation (NULL)
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync , mComponentDirLocation (NULL), mCurrProcDirLocation (NULL)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {}
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync
849851bf2ca145028b5729e48076e5723140affdvboxsync virtual ~DirectoryServiceProvider();
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync HRESULT init (const char *aCompRegLocation,
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync const char *aXPTIDatLocation,
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync const char *aComponentDirLocation,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *aCurrProcDirLocation);
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NS_DECL_NSIDIRECTORYSERVICEPROVIDER
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncprivate:
2849c1c13746836fae51db4f2a934e0a2de6f120vboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *mCompRegLocation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *mXPTIDatLocation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *mComponentDirLocation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *mCurrProcDirLocation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync};
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncNS_IMPL_ISUPPORTS1 (DirectoryServiceProvider, nsIDirectoryServiceProvider)
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync
fef7670f1122a99df607422af1622eb495f5ba4fvboxsyncDirectoryServiceProvider::~DirectoryServiceProvider()
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync{
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync if (mCompRegLocation)
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync {
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync RTStrFree (mCompRegLocation);
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync mCompRegLocation = NULL;
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync }
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync if (mXPTIDatLocation)
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync {
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync RTStrFree (mXPTIDatLocation);
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync mXPTIDatLocation = NULL;
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync }
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync if (mComponentDirLocation)
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync {
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync RTStrFree (mComponentDirLocation);
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync mComponentDirLocation = NULL;
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync }
42634b0ae449be8d087db91b81384bce7a5c21c3vboxsync if (mCurrProcDirLocation)
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync {
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync RTStrFree (mCurrProcDirLocation);
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync mCurrProcDirLocation = NULL;
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync }
42634b0ae449be8d087db91b81384bce7a5c21c3vboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param aCompRegLocation Path to compreg.dat, in Utf8.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @param aXPTIDatLocation Path to xpti.data, in Utf8.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
42634b0ae449be8d087db91b81384bce7a5c21c3vboxsyncHRESULT
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncDirectoryServiceProvider::init (const char *aCompRegLocation,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *aXPTIDatLocation,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *aComponentDirLocation,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *aCurrProcDirLocation)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertReturn(aCompRegLocation, NS_ERROR_INVALID_ARG);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertReturn(aXPTIDatLocation, NS_ERROR_INVALID_ARG);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int vrc = RTStrUtf8ToCurrentCP (&mCompRegLocation, aCompRegLocation);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(vrc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync vrc = RTStrUtf8ToCurrentCP (&mXPTIDatLocation, aXPTIDatLocation);
42634b0ae449be8d087db91b81384bce7a5c21c3vboxsync if (RT_SUCCESS(vrc) && aComponentDirLocation)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync vrc = RTStrUtf8ToCurrentCP (&mComponentDirLocation, aComponentDirLocation);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(vrc) && aCurrProcDirLocation)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync vrc = RTStrUtf8ToCurrentCP (&mCurrProcDirLocation, aCurrProcDirLocation);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RT_SUCCESS(vrc) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncNS_IMETHODIMP
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncDirectoryServiceProvider::GetFile (const char *aProp,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PRBool *aPersistent,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsIFile **aRetval)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsCOMPtr <nsILocalFile> localFile;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsresult rv = NS_ERROR_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *aRetval = nsnull;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *aPersistent = PR_TRUE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *fileLocation = NULL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (strcmp (aProp, NS_XPCOM_COMPONENT_REGISTRY_FILE) == 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fileLocation = mCompRegLocation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (strcmp (aProp, NS_XPCOM_XPTI_REGISTRY_FILE) == 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fileLocation = mXPTIDatLocation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (mComponentDirLocation && strcmp (aProp, NS_XPCOM_COMPONENT_DIR) == 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fileLocation = mComponentDirLocation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (mCurrProcDirLocation && strcmp (aProp, NS_XPCOM_CURRENT_PROCESS_DIR) == 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fileLocation = mCurrProcDirLocation;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync return NS_ERROR_FAILURE;
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rv = NS_NewNativeLocalFile (nsEmbedCString (fileLocation),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PR_TRUE, getter_AddRefs (localFile));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_FAILED(rv))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rv;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync return localFile->QueryInterface (NS_GET_IID (nsIFile),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync (void **) aRetval);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Global XPCOM initialization flag (we maintain it ourselves since XPCOM
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * doesn't provide such functionality)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic bool volatile gIsXPCOMInitialized = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Number of Initialize() calls on the main thread.
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic unsigned int gXPCOMInitCount = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync#else /* !defined (VBOX_WITH_XPCOM) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The COM main thread handle. (The first caller of com::Initialize().)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTTHREAD volatile gCOMMainThread = NIL_RTTHREAD;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Number of Initialize() calls on the main thread.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic uint32_t gCOMMainInitCount = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif /* !defined (VBOX_WITH_XPCOM) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/**
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Initializes the COM runtime.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * This method must be called on each thread of the client application that
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * wants to access COM facilities. The initialization must be performed before
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * calling any other COM method or attempting to instantiate COM objects.
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * On platforms using XPCOM, this method uses the following scheme to search for
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * XPCOM runtime:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * 1. If the VBOX_APP_HOME environment variable is set, the path it specifies
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * is used to search XPCOM libraries and components. If this method fails to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * initialize XPCOM runtime using this path, it will immediately return a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * failure and will NOT check for other paths as described below.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * 2. If VBOX_APP_HOME is not set, this methods tries the following paths in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * given order:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * a) Compiled-in application data directory (as returned by
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * RTPathAppPrivateArch())
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * b) "/usr/lib/virtualbox" (Linux only)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * c) "/opt/VirtualBox" (Linux only)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The first path for which the initialization succeeds will be used.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * On MS COM platforms, the COM runtime is provided by the system and does not
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * need to be searched for.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Once the COM subsystem is no longer necessary on a given thread, Shutdown()
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * must be called to free resources allocated for it. Note that a thread may
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * call Initialize() several times but for each of tese calls there must be a
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * corresponding Shutdown() call.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * @return S_OK on success and a COM result code in case of failure.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncHRESULT Initialize()
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync HRESULT rc = E_FAIL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if !defined (VBOX_WITH_XPCOM)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync DWORD flags = COINIT_MULTITHREADED |
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync COINIT_DISABLE_OLE1DDE |
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync COINIT_SPEED_OVER_MEMORY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = CoInitializeEx (NULL, flags);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// @todo the below rough method of changing the aparment type doesn't
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// work on some systems for unknown reason (CoUninitialize() simply does
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// nothing there, or at least all 10 000 of subsequent CoInitializeEx()
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// continue to return RPC_E_CHANGED_MODE there). The problem on those
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// systems is related to the "Extend support for advanced text services
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// to all programs" checkbox in the advanced language settings dialog,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// i.e. the problem appears when this checkbox is checked and disappears
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// if you clear it. For this reason, we disable the code below and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// instead initialize COM in MTA as early as possible, before 3rd party
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /// libraries we use have done so (i.e. Qt).
1859e17ebfeca9bb36190ecf145a6d023eae00b4vboxsync# if 0
1859e17ebfeca9bb36190ecf145a6d023eae00b4vboxsync /* If we fail to set the necessary apartment model, it may mean that some
1859e17ebfeca9bb36190ecf145a6d023eae00b4vboxsync * DLL that was indirectly loaded by the process calling this function has
1859e17ebfeca9bb36190ecf145a6d023eae00b4vboxsync * already initialized COM on the given thread in an incompatible way
1859e17ebfeca9bb36190ecf145a6d023eae00b4vboxsync * which we can't leave with. Therefore, we try to fix this by using the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * brute force method: */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc == RPC_E_CHANGED_MODE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Before we use brute force, we need to check if we are in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * neutral threaded apartment -- in this case there is no need to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * worry at all. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc == RPC_E_CHANGED_MODE)
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync {
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync /* This is a neutral apartment, reset the error */
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync rc = S_OK;
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync LogFlowFunc (("COM is already initialized in neutral threaded "
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync "apartment mode,\nwill accept it.\n"));
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync }
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync else if (rc == S_FALSE)
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* balance the test CoInitializeEx above */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync CoUninitialize();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RPC_E_CHANGED_MODE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LogFlowFunc (("COM is already initialized in single threaded "
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "apartment mode,\nwill reinitialize as "
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "multi threaded.\n"));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enum { MaxTries = 10000 };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int tries = MaxTries;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (rc == RPC_E_CHANGED_MODE && tries --)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync CoUninitialize();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = CoInitializeEx (NULL, flags);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc == S_OK)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* We've successfully reinitialized COM; restore the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * initialization reference counter */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LogFlowFunc (("Will call CoInitializeEx() %d times.\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync MaxTries - tries));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (tries ++ < MaxTries)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = CoInitializeEx (NULL, flags);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert (rc == S_FALSE);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
580e040eb04ce04ec23c4a2a32ee89445bedcc21vboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertMsgFailed (("rc=%08X\n", rc));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
42634b0ae449be8d087db91b81384bce7a5c21c3vboxsync /* the overall result must be either S_OK or S_FALSE (S_FALSE means
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * "already initialized using the same apartment model") */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertMsg (rc == S_OK || rc == S_FALSE, ("rc=%08X\n", rc));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* To be flow compatible with the XPCOM case, we return here if this isn't
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * the main thread or if it isn't its first initialization call.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Note! CoInitializeEx and CoUninitialize does it's own reference
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * counting, so this exercise is entirely for the EventQueue init. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fRc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTHREAD hSelf = RTThreadSelf (); Assert (hSelf != NIL_RTTHREAD);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMAtomicCmpXchgHandle (&gCOMMainThread, hSelf, NIL_RTTHREAD, fRc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!fRc)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( gCOMMainThread == hSelf
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && SUCCEEDED (rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync gCOMMainInitCount++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertComRC (rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert (RTThreadIsMain (hSelf));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* this is the first main thread initialization */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert (gCOMMainInitCount == 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (SUCCEEDED (rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync gCOMMainInitCount = 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#else /* !defined (VBOX_WITH_XPCOM) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ASMAtomicXchgBool (&gIsXPCOMInitialized, true) == true)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* XPCOM is already initialized on the main thread, no special
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * initialization is necessary on additional threads. Just increase
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * the init counter if it's a main thread again (to correctly support
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * nested calls to Initialize()/Shutdown() for compatibility with
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Win32). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsCOMPtr <nsIEventQueue> eventQ;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_GetMainEventQ (getter_AddRefs (eventQ));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PRBool isOnMainThread = PR_FALSE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = eventQ->IsOnCurrentThread (&isOnMainThread);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc) && isOnMainThread)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ++ gXPCOMInitCount;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertComRC (rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert (RTThreadIsMain (RTThreadSelf()));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* this is the first initialization */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync gXPCOMInitCount = 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool const fInitEventQueues = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* prepare paths for registry files */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char userHomeDir [RTPATH_MAX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int vrc = GetVBoxUserHomeDirectory (userHomeDir, sizeof (userHomeDir));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertRCReturn (vrc, NS_ERROR_FAILURE);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char compReg [RTPATH_MAX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char xptiDat [RTPATH_MAX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @todo use RTPathAppend */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrPrintf (compReg, sizeof (compReg), "%s%c%s",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync userHomeDir, RTPATH_DELIMITER, "compreg.dat");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrPrintf (xptiDat, sizeof (xptiDat), "%s%c%s",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync userHomeDir, RTPATH_DELIMITER, "xpti.dat");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LogFlowFunc (("component registry : \"%s\"\n", compReg));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LogFlowFunc (("XPTI data file : \"%s\"\n", xptiDat));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined (XPCOM_GLUE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync XPCOMGlueStartup (nsnull);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static const char *kAppPathsToProbe[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NULL, /* 0: will use VBOX_APP_HOME */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NULL, /* 1: will try RTPathAppPrivateArch() */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#ifdef RT_OS_LINUX
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "/usr/lib/virtualbox",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "/opt/VirtualBox",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#elif RT_OS_SOLARIS
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "/opt/VirtualBox/amd64",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "/opt/VirtualBox/i386",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#elif RT_OS_DARWIN
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "/Application/VirtualBox.app/Contents/MacOS",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Find out the directory where VirtualBox binaries are located */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (size_t i = 0; i < RT_ELEMENTS (kAppPathsToProbe); ++ i)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char appHomeDir [RTPATH_MAX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync appHomeDir [RTPATH_MAX - 1] = '\0';
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (i == 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Use VBOX_APP_HOME if present */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!RTEnvExist ("VBOX_APP_HOME"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync continue;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync strncpy (appHomeDir, RTEnvGet ("VBOX_APP_HOME"), RTPATH_MAX - 1); /** @todo r=bird: Use RTEnvGetEx. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (i == 1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Use RTPathAppPrivateArch() first */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync vrc = RTPathAppPrivateArch (appHomeDir, sizeof (appHomeDir));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertRC (vrc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(vrc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_ERROR_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync continue;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Iterate over all other paths */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync strncpy (appHomeDir, kAppPathsToProbe [i], RTPATH_MAX - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsCOMPtr <DirectoryServiceProvider> dsProv;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char compDir [RTPATH_MAX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrPrintf (compDir, sizeof (compDir), "%s%c%s",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync appHomeDir, RTPATH_DELIMITER, "components");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LogFlowFunc (("component directory : \"%s\"\n", compDir));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync dsProv = new DirectoryServiceProvider();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (dsProv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = dsProv->init (compReg, xptiDat, compDir, appHomeDir);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_ERROR_OUT_OF_MEMORY;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_FAILED (rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Setup the application path for NS_InitXPCOM2. Note that we properly
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * answer the NS_XPCOM_CURRENT_PROCESS_DIR query in our directory
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * service provider but it seems to be activated after the directory
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * service is used for the first time (see the source NS_InitXPCOM2). So
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * use the same value here to be on the safe side. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsCOMPtr <nsIFile> appDir;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *appDirCP = NULL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync vrc = RTStrUtf8ToCurrentCP (&appDirCP, appHomeDir);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(vrc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsCOMPtr <nsILocalFile> file;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_NewNativeLocalFile (nsEmbedCString (appDirCP),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PR_FALSE, getter_AddRefs (file));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync appDir = do_QueryInterface (file, &rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrFree (appDirCP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_ERROR_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_FAILED (rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync /* Set VBOX_XPCOM_HOME to the same app path to make XPCOM sources that
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync * still use it instead of the directory service happy */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *pathCP = NULL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync vrc = RTStrUtf8ToCurrentCP (&pathCP, appHomeDir);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(vrc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync vrc = RTEnvSet ("VBOX_XPCOM_HOME", pathCP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrFree (pathCP);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertRC (vrc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Finally, initialize XPCOM */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsCOMPtr <nsIServiceManager> serviceManager;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_InitXPCOM2 (getter_AddRefs (serviceManager),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync appDir, dsProv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsCOMPtr <nsIComponentRegistrar> registrar =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync do_QueryInterface (serviceManager, &rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = registrar->AutoRegister (nsnull);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* We succeeded, stop probing paths */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LogFlowFunc (("Succeeded.\n"));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* clean up before the new try */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_ShutdownXPCOM (nsnull);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (i == 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* We failed with VBOX_APP_HOME, don't probe other paths */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif /* !defined (VBOX_WITH_XPCOM) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertComRC (rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Init the main event queue (ASSUMES it cannot fail).
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (SUCCEEDED (rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync EventQueue::init();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncHRESULT Shutdown()
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync HRESULT rc = S_OK;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if !defined (VBOX_WITH_XPCOM)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* EventQueue::uninit reference counting fun. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTHREAD hSelf = RTThreadSelf();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( hSelf == gCOMMainThread
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && hSelf != NIL_RTTHREAD)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (-- gCOMMainInitCount == 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync EventQueue::uninit();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMAtomicWriteHandle (&gCOMMainThread, NIL_RTTHREAD);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync CoUninitialize();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#else /* !defined (VBOX_WITH_XPCOM) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync nsCOMPtr <nsIEventQueue> eventQ;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_GetMainEventQ (getter_AddRefs (eventQ));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc) || rc == NS_ERROR_NOT_AVAILABLE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* NS_ERROR_NOT_AVAILABLE seems to mean that
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * nsIEventQueue::StopAcceptingEvents() has been called (see
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * nsEventQueueService.cpp). We hope that this error code always means
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * just that in this case and assume that we're on the main thread
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * (it's a kind of unexpected behavior if a non-main thread ever calls
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * StopAcceptingEvents() on the main event queue). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PRBool isOnMainThread = PR_FALSE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = eventQ->IsOnCurrentThread (&isOnMainThread);
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync eventQ = nsnull; /* early release before shutdown */
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync }
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync else
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync {
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync isOnMainThread = PR_TRUE;
fef7670f1122a99df607422af1622eb495f5ba4fvboxsync rc = NS_OK;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (NS_SUCCEEDED(rc) && isOnMainThread)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* only the main thread needs to uninitialize XPCOM and only if
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * init counter drops to zero */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (-- gXPCOMInitCount == 0)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync EventQueue::uninit();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = NS_ShutdownXPCOM (nsnull);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* This is a thread initialized XPCOM and set gIsXPCOMInitialized to
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * true. Reset it back to false. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool wasInited = ASMAtomicXchgBool (&gIsXPCOMInitialized, false);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Assert (wasInited == true);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF (wasInited);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined (XPCOM_GLUE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync XPCOMGlueShutdown();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif /* !defined (VBOX_WITH_XPCOM) */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync AssertComRC (rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} /* namespace com */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync