VirtualBox

Changeset 35638 in vbox for trunk/src/VBox/Main/glue


Ignore:
Timestamp:
Jan 19, 2011 7:10:49 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
69546
Message:

Main. QT/FE: fix long standing COM issue

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/glue/initterm.cpp

    r33540 r35638  
    247247 * @return S_OK on success and a COM result code in case of failure.
    248248 */
    249 HRESULT Initialize()
     249HRESULT Initialize(bool fGui)
    250250{
    251251    HRESULT rc = E_FAIL;
     
    253253#if !defined(VBOX_WITH_XPCOM)
    254254
    255     DWORD flags = COINIT_MULTITHREADED
     255    /**
     256      * We initialize COM in GUI thread in STA, to be compliant with QT and
     257      * OLE requirments (for example to allow D&D), while other threads
     258      * initialized in regular MTA. To allow fast proxyless access from
     259      * GUI thread to COM objects, we explicitly provide our COM objects
     260      * with free threaded marshaller.
     261      * !!!!! Please think twice before touching this code !!!!!
     262      */
     263    DWORD flags = fGui ?
     264                  COINIT_APARTMENTTHREADED
     265                | COINIT_SPEED_OVER_MEMORY
     266                :
     267                  COINIT_MULTITHREADED
    256268                | COINIT_DISABLE_OLE1DDE
    257269                | COINIT_SPEED_OVER_MEMORY;
    258270
    259271    rc = CoInitializeEx(NULL, flags);
    260 
    261     /// @todo the below rough method of changing the apartment type doesn't
    262     /// work on some systems for unknown reason (CoUninitialize() simply does
    263     /// nothing there, or at least all 10 000 of subsequent CoInitializeEx()
    264     /// continue to return RPC_E_CHANGED_MODE there). The problem on those
    265     /// systems is related to the "Extend support for advanced text services
    266     /// to all programs" checkbox in the advanced language settings dialog,
    267     /// i.e. the problem appears when this checkbox is checked and disappears
    268     /// if you clear it. For this reason, we disable the code below and
    269     /// instead initialize COM in MTA as early as possible, before 3rd party
    270     /// libraries we use have done so (i.e. Qt).
    271 # if 0
    272     /* If we fail to set the necessary apartment model, it may mean that some
    273      * DLL that was indirectly loaded by the process calling this function has
    274      * already initialized COM on the given thread in an incompatible way
    275      * which we can't leave with. Therefore, we try to fix this by using the
    276      * brute force method: */
    277 
    278     if (rc == RPC_E_CHANGED_MODE)
    279     {
    280         /* Before we use brute force, we need to check if we are in the
    281          * neutral threaded apartment -- in this case there is no need to
    282          * worry at all. */
    283 
    284         rc = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    285         if (rc == RPC_E_CHANGED_MODE)
    286         {
    287             /* This is a neutral apartment, reset the error */
    288             rc = S_OK;
    289 
    290             LogFlowFunc(("COM is already initialized in neutral threaded "
    291                          "apartment mode,\nwill accept it.\n"));
    292         }
    293         else if (rc == S_FALSE)
    294         {
    295             /* balance the test CoInitializeEx above */
    296             CoUninitialize();
    297             rc = RPC_E_CHANGED_MODE;
    298 
    299             LogFlowFunc(("COM is already initialized in single threaded "
    300                          "apartment mode,\nwill reinitialize as "
    301                          "multi threaded.\n"));
    302 
    303             enum { MaxTries = 10000 };
    304             int tries = MaxTries;
    305             while (rc == RPC_E_CHANGED_MODE && tries --)
    306             {
    307                 CoUninitialize();
    308                 rc = CoInitializeEx(NULL, flags);
    309                 if (rc == S_OK)
    310                 {
    311                     /* We've successfully reinitialized COM; restore the
    312                      * initialization reference counter */
    313 
    314                     LogFlowFunc(("Will call CoInitializeEx() %d times.\n",
    315                                  MaxTries - tries));
    316 
    317                     while (tries ++ < MaxTries)
    318                     {
    319                         rc = CoInitializeEx(NULL, flags);
    320                         Assert(rc == S_FALSE);
    321                     }
    322                 }
    323             }
    324         }
    325         else
    326             AssertMsgFailed(("rc=%08X\n", rc));
    327     }
    328 # endif
    329272
    330273    /* the overall result must be either S_OK or S_FALSE (S_FALSE means
     
    342285    else
    343286        fRc = false;
     287
     288    if (fGui)
     289           Assert(RTThreadIsMain(hSelf));
     290
    344291    if (!fRc)
    345292    {
     
    359306
    360307#else /* !defined (VBOX_WITH_XPCOM) */
     308
     309     /* Unused here */
     310    (void)fGui;
    361311
    362312    if (ASMAtomicXchgBool(&gIsXPCOMInitialized, true) == true)
Note: See TracChangeset for help on using the changeset viewer.

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