Logo Search packages:      
Sourcecode: virtualbox-ose version File versions

HRESULT com::Initialize ( void   ) 

Initializes the COM runtime. Must be called on every thread that uses COM, before any COM activity.

Returns:
COM result code

Todo:
the below rough method of changing the aparment type doesn't work on some systems for unknown reason (CoUninitialize() simply does nothing there, or at least all 10 000 of subsequent CoInitializeEx() continue to return RPC_E_CHANGED_MODE there). The problem on those systems is related to the "Extend support for advanced text services to all programs" checkbox in the advanced language settings dialog, i.e. the problem appears when this checkbox is checked and disappears if you clear it. For this reason, we disable the code below and instead initialize COM in MTA as early as possible, before 3rd party libraries we use have done so (i.e. Qt3).

Definition at line 194 of file initterm.cpp.

References Assert, AssertComRC, AssertMsg, AssertMsgFailed, AssertRC, DWORD, GetVBoxUserHomeDirectory(), LogFlowFunc, NULL, RT_SUCCESS, RTPATH_DELIMITER, and RTPATH_MAX.

Referenced by COMBase::InitializeCOM(), and main().

{
    HRESULT rc = E_FAIL;

#if !defined (VBOX_WITH_XPCOM)

    DWORD flags = COINIT_MULTITHREADED |
                  COINIT_DISABLE_OLE1DDE |
                  COINIT_SPEED_OVER_MEMORY;

    rc = CoInitializeEx (NULL, flags);

    /// @todo the below rough method of changing the aparment type doesn't
    /// work on some systems for unknown reason (CoUninitialize() simply does
    /// nothing there, or at least all 10 000 of subsequent CoInitializeEx()
    /// continue to return RPC_E_CHANGED_MODE there). The problem on those
    /// systems is related to the "Extend support for advanced text services
    /// to all programs" checkbox in the advanced language settings dialog,
    /// i.e. the problem appears when this checkbox is checked and disappears
    /// if you clear it. For this reason, we disable the code below and
    /// instead initialize COM in MTA as early as possible, before 3rd party
    /// libraries we use have done so (i.e. Qt3).
#if 0
    /* If we fail to set the necessary apartment model, it may mean that some
     * DLL that was indirectly loaded by the process calling this function has
     * already initialized COM on the given thread in an incompatible way
     * which we can't leave with. Therefore, we try to fix this by using the
     * brute force method: */

    if (rc == RPC_E_CHANGED_MODE)
    {
        /* Before we use brute force, we need to check if we are in the
         * neutral threaded apartment -- in this case there is no need to
         * worry at all. */

        rc = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
        if (rc == RPC_E_CHANGED_MODE)
        {
            /* This is a neutral apartment, reset the error */
            rc = S_OK;

            LogFlowFunc (("COM is already initialized in neutral threaded "
                          "apartment mode,\nwill accept it.\n"));
        }
        else if (rc == S_FALSE)
        {
            /* balance the test CoInitializeEx above */
            CoUninitialize();
            rc = RPC_E_CHANGED_MODE;

            LogFlowFunc (("COM is already initialized in single threaded "
                          "apartment mode,\nwill reinitialize as "
                          "multi threaded.\n"));

            enum { MaxTries = 10000 };
            int tries = MaxTries;
            while (rc == RPC_E_CHANGED_MODE && tries --)
            {
                CoUninitialize();
                rc = CoInitializeEx (NULL, flags);
                if (rc == S_OK)
                {
                    /* We've successfully reinitialized COM; restore the
                     * initialization reference counter */

                    LogFlowFunc (("Will call CoInitializeEx() %d times.\n",
                                  MaxTries - tries));

                    while (tries ++ < MaxTries)
                    {
                        rc = CoInitializeEx (NULL, flags);
                        Assert (rc == S_FALSE);
                    }
                }
            }
        }
        else
            AssertMsgFailed (("rc=%08X\n", rc));
    }
#endif

    /* the overall result must be either S_OK or S_FALSE (S_FALSE means
     * "already initialized using the same apartment model") */
    AssertMsg (rc == S_OK || rc == S_FALSE, ("rc=%08X\n", rc));

#else /* !defined (VBOX_WITH_XPCOM) */

    if (ASMAtomicXchgBool (&gIsXPCOMInitialized, true) == true)
    {
        /* XPCOM is already initialized on the main thread, no special
         * initialization is necessary on additional threads. Just increase
         * the init counter if it's a main thread again (to correctly support
         * nested calls to Initialize()/Shutdown() for compatibility with
         * Win32). */

        nsCOMPtr <nsIEventQueue> eventQ;
        rc = NS_GetMainEventQ (getter_AddRefs (eventQ));

        if (NS_SUCCEEDED (rc))
        {
            PRBool isOnMainThread = PR_FALSE;
            rc = eventQ->IsOnCurrentThread (&isOnMainThread);
            if (NS_SUCCEEDED (rc) && isOnMainThread)
                ++ gXPCOMInitCount;
        }

        AssertComRC (rc);
        return rc;
    }

    /* this is the first initialization */
    gXPCOMInitCount = 1;

    /* Set VBOX_XPCOM_HOME if not present */
    if (!RTEnvExist ("VBOX_XPCOM_HOME"))
    {
        /* get the executable path */
        char pathProgram [RTPATH_MAX];
        int vrc = RTPathProgram (pathProgram, sizeof (pathProgram));
        if (RT_SUCCESS (vrc))
        {
            char *pathProgramCP = NULL;
            vrc = RTStrUtf8ToCurrentCP (&pathProgramCP, pathProgram);
            if (RT_SUCCESS (vrc))
            {
                vrc = RTEnvSet ("VBOX_XPCOM_HOME", pathProgramCP);
                RTStrFree (pathProgramCP);
            }
        }
        AssertRC (vrc);
    }

#if defined (XPCOM_GLUE)
    XPCOMGlueStartup (nsnull);
#endif

    nsCOMPtr <DirectoryServiceProvider> dsProv;

    /* prepare paths for registry files */
    char homeDir [RTPATH_MAX];
    char privateArchDir [RTPATH_MAX];
    int vrc = GetVBoxUserHomeDirectory (homeDir, sizeof (homeDir));
    if (RT_SUCCESS (vrc))
        vrc = RTPathAppPrivateArch (privateArchDir, sizeof (privateArchDir));
    if (RT_SUCCESS (vrc))
    {
        char compReg [RTPATH_MAX];
        char xptiDat [RTPATH_MAX];
        char compDir [RTPATH_MAX];

        RTStrPrintf (compReg, sizeof (compReg), "%s%c%s",
                     homeDir, RTPATH_DELIMITER, "compreg.dat");
        RTStrPrintf (xptiDat, sizeof (xptiDat), "%s%c%s",
                     homeDir, RTPATH_DELIMITER, "xpti.dat");
        RTStrPrintf (compDir, sizeof (compDir), "%s%c%s",
                     privateArchDir, RTPATH_DELIMITER, "components");

        LogFlowFunc (("component registry  : \"%s\"\n", compReg));
        LogFlowFunc (("XPTI data file      : \"%s\"\n", xptiDat));
        LogFlowFunc (("component directory : \"%s\"\n", compDir));

        dsProv = new DirectoryServiceProvider();
        if (dsProv)
            rc = dsProv->init (compReg, xptiDat, compDir, privateArchDir);
        else
            rc = NS_ERROR_OUT_OF_MEMORY;
    }
    else
        rc = NS_ERROR_FAILURE;

    if (NS_SUCCEEDED (rc))
    {
        /* get the path to the executable */
        nsCOMPtr <nsIFile> appDir;
        {
            char path [RTPATH_MAX];
            char *appDirCP = NULL;
#if defined (DEBUG)
            const char *env = RTEnvGet ("VIRTUALBOX_APP_HOME");
            if (env)
            {
                char *appDirUtf8 = NULL;
                vrc = RTStrCurrentCPToUtf8 (&appDirUtf8, env);
                if (RT_SUCCESS (vrc))
                {
                    vrc = RTPathReal (appDirUtf8, path, RTPATH_MAX);
                    if (RT_SUCCESS (vrc))
                        vrc = RTStrUtf8ToCurrentCP (&appDirCP, appDirUtf8);
                    RTStrFree (appDirUtf8);
                }
            }
            else
#endif
            {
                vrc = RTPathProgram (path, RTPATH_MAX);
                if (RT_SUCCESS (vrc))
                    vrc = RTStrUtf8ToCurrentCP (&appDirCP, path);
            }

            if (RT_SUCCESS (vrc))
            {
                nsCOMPtr <nsILocalFile> file;
                rc = NS_NewNativeLocalFile (nsEmbedCString (appDirCP),
                                            PR_FALSE, getter_AddRefs (file));
                if (NS_SUCCEEDED (rc))
                    appDir = do_QueryInterface (file, &rc);

                RTStrFree (appDirCP);
            }
            else
                rc = NS_ERROR_FAILURE;
        }

        /* Finally, initialize XPCOM */
        if (NS_SUCCEEDED (rc))
        {
            nsCOMPtr <nsIServiceManager> serviceManager;
            rc = NS_InitXPCOM2 (getter_AddRefs (serviceManager),
                                appDir, dsProv);

            if (NS_SUCCEEDED (rc))
            {
                nsCOMPtr <nsIComponentRegistrar> registrar =
                    do_QueryInterface (serviceManager, &rc);
                if (NS_SUCCEEDED (rc))
                    registrar->AutoRegister (nsnull);
            }
        }
    }

#endif /* !defined (VBOX_WITH_XPCOM) */

    AssertComRC (rc);

    return rc;
}


Generated by  Doxygen 1.6.0   Back to index