VirtualBox

Changeset 4862 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 17, 2007 5:28:24 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
24584
Message:

Main/GUI/Win32: Don't apply the brute force STA to MTA change hack since it doesn't work on all systems; instead initialize COM before Qt to enter MTA first.

Location:
trunk/src/VBox
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp

    r4775 r4862  
    34773477#endif
    34783478
     3479#ifdef Q_WS_WIN
     3480    /* COM for the main thread is initialized in main() */
     3481#else
    34793482    HRESULT rc = COMBase::initializeCOM();
    34803483    if (FAILED (rc))
     
    34833486        return;
    34843487    }
     3488#endif
    34853489
    34863490    vbox.createInstance (CLSID_VirtualBox);
     
    37283732    QApplication::removePostedEvents (this);
    37293733
     3734#ifdef Q_WS_WIN
     3735    /* COM for the main thread is shutdown in main() */
     3736#else
    37303737    COMBase::cleanupCOM();
     3738#endif
    37313739
    37323740    valid = false;
  • trunk/src/VBox/Frontends/VirtualBox/src/main.cpp

    r4590 r4862  
    117117    LogFlowFuncEnter();
    118118
     119#ifdef Q_WS_WIN
     120    /* Initialize COM early, before QApplication calls OleInitialize(), to
     121     * make sure we enter the multi threded apartment instead of a single
     122     * threaded one. Note that this will make some non-threadsafe system
     123     * services that use OLE and require STA (such as Drag&Drop) not work
     124     * anymore, however it's still better because otherwise VBox will not work
     125     * on some Windows XP systems at all since it requires MTA (we cannot
     126     * leave STA by calling CoUninitialize() and re-enter MTA on those systems
     127     * for some unknown reason), see also src/VBox/Main/glue/initterm.cpp. */
     128    /// @todo find a proper solution that satisfies both OLE and VBox
     129    HRESULT hrc = COMBase::initializeCOM();
     130#endif
     131
    119132#if defined(DEBUG) && defined(Q_WS_X11)
    120133    /* install our signal handler to backtrace the call stack */
     
    130143    qInstallMsgHandler (QtMessageOutput);
    131144
    132     QIApplication a (argc, argv);
    133 
    134 #ifdef Q_WS_WIN
    135     /* Drag in the sound drivers and DLLs early to get rid of the delay taking
    136      * place when the main menu bar (or any action from that menu bar) is
    137      * activated for the first time. This delay is especially annoying if it
    138      * happens when the VM is executing in real mode (which gives 100% CPU
    139      * load and slows down the load process that happens on the main GUI
    140      * thread to several seconds). */
    141     PlaySound (NULL, NULL, 0);
     145    int rc = 1; /* failure */
     146
     147    /* scope the QIApplication variable */
     148    {
     149        QIApplication a (argc, argv);
     150
     151#ifdef Q_WS_WIN
     152        /* Drag in the sound drivers and DLLs early to get rid of the delay taking
     153         * place when the main menu bar (or any action from that menu bar) is
     154         * activated for the first time. This delay is especially annoying if it
     155         * happens when the VM is executing in real mode (which gives 100% CPU
     156         * load and slows down the load process that happens on the main GUI
     157         * thread to several seconds). */
     158        PlaySound (NULL, NULL, 0);
    142159#endif
    143160
    144161#ifndef RT_OS_DARWIN
    145     /* some gui qt-styles has it's own different color for buttons
    146      * causing tool-buttons and dropped menu displayed in
    147      * different annoying color, so fixing palette button's color */
    148     QPalette pal = a.palette();
    149     pal.setColor (QPalette::Disabled, QColorGroup::Button,
    150                   pal.color (QPalette::Disabled, QColorGroup::Background));
    151     pal.setColor (QPalette::Active, QColorGroup::Button,
    152                   pal.color (QPalette::Active, QColorGroup::Background));
    153     pal.setColor (QPalette::Inactive, QColorGroup::Button,
    154                   pal.color (QPalette::Inactive, QColorGroup::Background));
    155     a.setPalette (pal);
    156 #endif
    157 
    158 #ifdef Q_WS_X11
    159     /* version check (major.minor are sensitive, fix number is ignored) */
    160     QString ver_str = QString::fromLatin1 (QT_VERSION_STR);
    161     QString ver_str_base = ver_str.section ('.', 0, 1);
    162     QString rt_ver_str = QString::fromLatin1 (qVersion());
    163     uint ver =
    164         (ver_str.section ('.', 0, 0).toInt() << 16) +
    165         (ver_str.section ('.', 1, 1).toInt() << 8) +
    166         ver_str.section ('.', 2, 2).toInt();
    167     uint rt_ver =
    168         (rt_ver_str.section ('.', 0, 0).toInt() << 16) +
    169         (rt_ver_str.section ('.', 1, 1).toInt() << 8) +
    170         rt_ver_str.section ('.', 2, 2).toInt();
    171     if (rt_ver < (ver & 0xFFFF00)) {
    172         QString msg =
    173             QApplication::tr ("Executable <b>%1</b> requires Qt %2.x, found Qt %3.")
    174                 .arg (QString::fromLatin1 (qAppName()))
    175                 .arg (ver_str_base)
    176                 .arg (rt_ver_str);
    177         QMessageBox::critical (
    178             0, QApplication::tr ("Incompatible Qt Library Error"),
    179             msg, QMessageBox::Abort, 0
    180         );
    181         qFatal (msg.ascii());
     162        /* some gui qt-styles has it's own different color for buttons
     163         * causing tool-buttons and dropped menu displayed in
     164         * different annoying color, so fixing palette button's color */
     165        QPalette pal = a.palette();
     166        pal.setColor (QPalette::Disabled, QColorGroup::Button,
     167                      pal.color (QPalette::Disabled, QColorGroup::Background));
     168        pal.setColor (QPalette::Active, QColorGroup::Button,
     169                      pal.color (QPalette::Active, QColorGroup::Background));
     170        pal.setColor (QPalette::Inactive, QColorGroup::Button,
     171                      pal.color (QPalette::Inactive, QColorGroup::Background));
     172        a.setPalette (pal);
     173#endif
     174
     175#ifdef Q_WS_X11
     176        /* version check (major.minor are sensitive, fix number is ignored) */
     177        QString ver_str = QString::fromLatin1 (QT_VERSION_STR);
     178        QString ver_str_base = ver_str.section ('.', 0, 1);
     179        QString rt_ver_str = QString::fromLatin1 (qVersion());
     180        uint ver =
     181            (ver_str.section ('.', 0, 0).toInt() << 16) +
     182            (ver_str.section ('.', 1, 1).toInt() << 8) +
     183            ver_str.section ('.', 2, 2).toInt();
     184        uint rt_ver =
     185            (rt_ver_str.section ('.', 0, 0).toInt() << 16) +
     186            (rt_ver_str.section ('.', 1, 1).toInt() << 8) +
     187            rt_ver_str.section ('.', 2, 2).toInt();
     188        if (rt_ver < (ver & 0xFFFF00))
     189        {
     190            QString msg =
     191                QApplication::tr ("Executable <b>%1</b> requires Qt %2.x, found Qt %3.")
     192                                  .arg (QString::fromLatin1 (qAppName()))
     193                                  .arg (ver_str_base)
     194                                  .arg (rt_ver_str);
     195            QMessageBox::critical (
     196                0, QApplication::tr ("Incompatible Qt Library Error"),
     197                msg, QMessageBox::Abort, 0);
     198            qFatal (msg.ascii());
     199        }
     200#endif
     201
     202        /* load a translation based on the current locale */
     203        VBoxGlobal::loadLanguage();
     204
     205        do
     206        {
     207#ifdef Q_WS_WIN
     208            /* Check for the COM error after we've initialized Qt */
     209            if (FAILED (hrc))
     210            {
     211                vboxProblem().cannotInitCOM (hrc);
     212                break;
     213            }
     214#endif
     215
     216            if (!vboxGlobal().isValid())
     217                break;
     218
     219#ifndef VBOX_OSE
     220#ifdef Q_WS_X11
     221            /* show the user license file */
     222            if (!vboxGlobal().showVirtualBoxLicense())
     223                break;
     224#endif
     225#endif
     226
     227            VBoxGlobalSettings settings = vboxGlobal().settings();
     228            /* Process known keys */
     229            bool noSelector = settings.isFeatureActive ("noSelector");
     230
     231            if (vboxGlobal().isVMConsoleProcess())
     232            {
     233                a.setMainWidget( &vboxGlobal().consoleWnd());
     234                if (vboxGlobal().startMachine (vboxGlobal().managedVMUuid()))
     235                    rc = a.exec();
     236            }
     237            else if (noSelector)
     238            {
     239                vboxProblem().cannotRunInSelectorMode();
     240            }
     241            else
     242            {
     243                a.setMainWidget (&vboxGlobal().selectorWnd());
     244                vboxGlobal().selectorWnd().show();
     245                vboxGlobal().startEnumeratingMedia();
     246                rc = a.exec();
     247            }
     248        }
     249        while (0);
    182250    }
    183 #endif
    184 
    185     /* load a translation based on the current locale */
    186     VBoxGlobal::loadLanguage();
    187 
    188     int rc = 1;
    189 
    190     if (vboxGlobal().isValid())
    191     {
    192 #ifndef VBOX_OSE
    193 #ifdef Q_WS_X11
    194         /* show the user license file */
    195         if (!vboxGlobal().showVirtualBoxLicense())
    196             return rc;
    197 #endif
    198 #endif
    199 
    200         VBoxGlobalSettings settings = vboxGlobal().settings();
    201         /* Process known keys */
    202         bool noSelector = settings.isFeatureActive ("noSelector");
    203 
    204         if (vboxGlobal().isVMConsoleProcess())
    205         {
    206             a.setMainWidget( &vboxGlobal().consoleWnd());
    207             if (vboxGlobal().startMachine (vboxGlobal().managedVMUuid()))
    208                 rc = a.exec();
    209         }
    210         else if (noSelector)
    211         {
    212             vboxProblem().cannotRunInSelectorMode();
    213         }
    214         else
    215         {
    216             a.setMainWidget (&vboxGlobal().selectorWnd());
    217             vboxGlobal().selectorWnd().show();
    218             vboxGlobal().startEnumeratingMedia();
    219             rc = a.exec();
    220         }
    221     }
     251
     252#ifdef Q_WS_WIN
     253    /* See COMBase::initializeCOM() above */
     254    if (SUCCEEDED (hrc))
     255        COMBase::cleanupCOM();
     256#endif
    222257
    223258    LogFlowFunc (("rc=%d\n", rc));
  • trunk/src/VBox/Main/glue/initterm.cpp

    r4737 r4862  
    178178    rc = CoInitializeEx (NULL, flags);
    179179
     180    /// @todo the below rough method of changing the aparment type doesn't
     181    /// work on some systems for unknown reason (CoUninitialize() simply does
     182    /// nothing there, or at least all 10 000 of subsequent CoInitializeEx()
     183    /// continue to return RPC_E_CHANGED_MODE there). The problem on those
     184    /// systems is related to the "Extend support for advanced text services
     185    /// to all programs" checkbox in the advanced language settings dialog,
     186    /// i.e. the problem appears when this checkbox is checked and disappears
     187    /// if you clear it. For this reason, we disable the code below and
     188    /// instead initialize COM in MTA as early as possible, before 3rd party
     189    /// libraries we use have done so (i.e. Qt3).
     190#if 0
    180191    /* If we fail to set the necessary apartment model, it may mean that some
    181192     * DLL that was indirectly loaded by the process calling this function has
     
    186197    if (rc == RPC_E_CHANGED_MODE)
    187198    {
    188         LogFlowFunc (("COM already initialized in wrong apartment mode, "
    189                       "will reinitialize.\n"));
    190 
    191         enum { MaxTries = 10000 };
    192         int tries = MaxTries;
    193         while (rc == RPC_E_CHANGED_MODE && tries --)
    194         {
     199        /* Before we use brute force, we need to check if we are in the
     200         * neutral threaded apartment -- in this case there is no need to
     201         * worry at all. */
     202
     203        rc = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
     204        if (rc == RPC_E_CHANGED_MODE)
     205        {
     206            /* This is a neutral apartment, reset the error */
     207            rc = S_OK;
     208
     209            LogFlowFunc (("COM is already initialized in neutral threaded "
     210                          "apartment mode,\nwill accept it.\n"));
     211        }
     212        else if (rc == S_FALSE)
     213        {
     214            /* balance the test CoInitializeEx above */
    195215            CoUninitialize();
    196             rc = CoInitializeEx (NULL, flags);
    197             if (rc == S_OK)
    198             {
    199                 /* We've successfully reinitialized COM; restore the
    200                  * initialization reference counter */
    201 
    202                 LogFlowFunc (("Will call CoInitializeEx() %d times.\n",
    203                               MaxTries - tries));
    204 
    205                 while (tries ++ < MaxTries)
     216            rc = RPC_E_CHANGED_MODE;
     217
     218            LogFlowFunc (("COM is already initialized in single threaded "
     219                          "apartment mode,\nwill reinitialize as "
     220                          "multi threaded.\n"));
     221
     222            enum { MaxTries = 10000 };
     223            int tries = MaxTries;
     224            while (rc == RPC_E_CHANGED_MODE && tries --)
     225            {
     226                CoUninitialize();
     227                rc = CoInitializeEx (NULL, flags);
     228                if (rc == S_OK)
    206229                {
    207                     rc = CoInitializeEx (NULL, flags);
    208                     Assert (rc == S_FALSE);
     230                    /* We've successfully reinitialized COM; restore the
     231                     * initialization reference counter */
     232
     233                    LogFlowFunc (("Will call CoInitializeEx() %d times.\n",
     234                                  MaxTries - tries));
     235
     236                    while (tries ++ < MaxTries)
     237                    {
     238                        rc = CoInitializeEx (NULL, flags);
     239                        Assert (rc == S_FALSE);
     240                    }
    209241                }
    210242            }
    211243        }
    212     }
     244        else
     245            AssertMsgFailed (("rc=%08X\n", rc));
     246    }
     247#endif
    213248
    214249    /* the overall result must be either S_OK or S_FALSE (S_FALSE means
Note: See TracChangeset for help on using the changeset viewer.

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