VirtualBox

Changeset 63814 in vbox for trunk


Ignore:
Timestamp:
Sep 13, 2016 2:53:10 PM (8 years ago)
Author:
vboxsync
Message:

VirtualBoxClientImpl.cpp: Added code investingating known E_NOINTERFACE/REGDB_E_CLASSNOTREG problems and come up with a more detailed error message.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/VirtualBoxClientImpl.h

    r63643 r63814  
    6767    static uint32_t g_cInstances;
    6868
     69#ifdef RT_OS_WINDOWS
     70    virtual HRESULT i_investigateVirtualBoxObjectCreationFailure(HRESULT hrc);
     71#endif
     72
    6973    static DECLCALLBACK(int) SVCWatcherThread(RTTHREAD ThreadSelf, void *pvUser);
    7074
  • trunk/src/VBox/Main/src-client/VirtualBoxClientImpl.cpp

    r63639 r63814  
    2828#include <iprt/semaphore.h>
    2929#include <iprt/cpp/utils.h>
     30#ifdef RT_OS_WINDOWS
     31# include <iprt/ldr.h>
     32# include <msi.h>
     33#endif
    3034
    3135
     
    9195        rc = mData.m_pVirtualBox.createLocalObject(CLSID_VirtualBox);
    9296        if (FAILED(rc))
     97#ifdef RT_OS_WINDOWS
     98            throw i_investigateVirtualBoxObjectCreationFailure(rc);
     99#else
    93100            throw rc;
     101#endif
    94102
    95103        /* VirtualBox error return is postponed to method calls, fetch it. */
     
    156164    return S_OK;
    157165}
     166
     167#ifdef RT_OS_WINDOWS
     168/**
     169 * Looks into why we failed to create the VirtualBox object.
     170 *
     171 * @returns hrcCaller thru setError.
     172 * @param   hrcCaller   The failure status code.
     173 */
     174HRESULT VirtualBoxClient::i_investigateVirtualBoxObjectCreationFailure(HRESULT hrcCaller)
     175{
     176    /*
     177     * First step is to try get an IUnknown interface of the VirtualBox object.
     178     *
     179     * This will succeed even when oleaut32.msm (see @bugref{8016}, @ticketref{12087})
     180     * is accidentally installed and messes up COM.  It may also succeed when the COM
     181     * registration is partially broken (though that's unlikely to happen these days).
     182     */
     183    IUnknown *pUnknown = NULL;
     184    HRESULT hrc = CoCreateInstance(CLSID_VirtualBox, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void **)&pUnknown);
     185    if (FAILED(hrc))
     186    {
     187        if (hrc == hrcCaller)
     188            return setError(hrcCaller, tr("Completely failed to instantiate CLSID_VirtualBox: %Rhrc"), hrcCaller);
     189        return setError(hrcCaller, tr("Completely failed to instantiate CLSID_VirtualBox: %Rhrc & %Rhrc"), hrcCaller, hrc);
     190    }
     191
     192    /*
     193     * Try query the IVirtualBox interface (should fail), if it succeed we return
     194     * straight away so we have more columns to spend on long messages below.
     195     */
     196    IVirtualBox *pVirtualBox;
     197    hrc = pUnknown->QueryInterface(IID_IVirtualBox, (void **)&pVirtualBox);
     198    if (SUCCEEDED(hrc))
     199    {
     200        pVirtualBox->Release();
     201        pUnknown->Release();
     202        return setError(hrcCaller,
     203                        tr("Failed to instantiate CLSID_VirtualBox the first time, but worked when checking out why ... weird"));
     204    }
     205
     206    /*
     207     * Check for oleaut32.msm traces in the registry.
     208     */
     209    HKEY hKey;
     210    LSTATUS lrc = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID\\{00020420-0000-0000-C000-000000000046}\\InprocServer32",
     211                                0 /*fFlags*/, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | STANDARD_RIGHTS_READ, &hKey);
     212    if (lrc == ERROR_SUCCESS)
     213    {
     214        wchar_t wszBuf[8192];
     215        DWORD   cbBuf  = sizeof(wszBuf) - sizeof(wchar_t);
     216        DWORD   dwType = 0;
     217        lrc = RegQueryValueExW(hKey, L"InprocServer32", NULL /*pvReserved*/, &dwType, (BYTE *)&wszBuf[0], &cbBuf);
     218        if (lrc == ERROR_SUCCESS)
     219        {
     220            wszBuf[cbBuf / sizeof(wchar_t)] = '\0';
     221            bool fSetError = false;
     222
     223            /*
     224             * Try decode the string and improve the message.
     225             */
     226            typedef UINT (WINAPI *PFNMSIDECOMPOSEDESCRIPTORW)(PCWSTR pwszDescriptor,
     227                                                              LPWSTR pwszProductCode /*[40]*/,
     228                                                              LPWSTR pwszFeatureId /*[40]*/,
     229                                                              LPWSTR pwszComponentCode /*[40]*/,
     230                                                              DWORD *poffArguments);
     231            PFNMSIDECOMPOSEDESCRIPTORW pfnMsiDecomposeDescriptorW;
     232            pfnMsiDecomposeDescriptorW = (PFNMSIDECOMPOSEDESCRIPTORW)RTLdrGetSystemSymbol("msi.dll", "MsiDecomposeDescriptorW");
     233            if (   pfnMsiDecomposeDescriptorW
     234                && (   dwType == REG_SZ
     235                    || dwType == REG_MULTI_SZ))
     236            {
     237                wchar_t wszProductCode[RTUUID_STR_LENGTH + 2 + 16]   = { 0 };
     238                wchar_t wszFeatureId[RTUUID_STR_LENGTH + 2 + 16]     = { 0 };
     239                wchar_t wszComponentCode[RTUUID_STR_LENGTH + 2 + 16] = { 0 };
     240                DWORD   offArguments = ~(DWORD)0;
     241                UINT uRc = pfnMsiDecomposeDescriptorW(wszBuf, wszProductCode, wszFeatureId, wszComponentCode, &offArguments);
     242                if (uRc == 0)
     243                {
     244                    /*
     245                     * Can we resolve the product code into a name?
     246                     */
     247                    typedef UINT (WINAPI *PFNMSIOPENPRODUCTW)(PCWSTR, MSIHANDLE *);
     248                    PFNMSIOPENPRODUCTW pfnMsiOpenProductW;
     249                    pfnMsiOpenProductW = (PFNMSIOPENPRODUCTW)RTLdrGetSystemSymbol("msi.dll", "MsiOpenProductW");
     250
     251                    typedef UINT (WINAPI *PFNMSICLOSEHANDLE)(MSIHANDLE);
     252                    PFNMSICLOSEHANDLE pfnMsiCloseHandle;
     253                    pfnMsiCloseHandle = (PFNMSICLOSEHANDLE)RTLdrGetSystemSymbol("msi.dll", "MsiCloseHandle");
     254
     255                    typedef UINT (WINAPI *PFNGETPRODUCTPROPERTYW)(MSIHANDLE, PCWSTR, PWSTR, PDWORD);
     256                    PFNGETPRODUCTPROPERTYW pfnMsiGetProductPropertyW;
     257                    pfnMsiGetProductPropertyW = (PFNGETPRODUCTPROPERTYW)RTLdrGetSystemSymbol("msi.dll", "MsiGetProductPropertyW");
     258                    if (   pfnMsiGetProductPropertyW
     259                        && pfnMsiCloseHandle
     260                        && pfnMsiOpenProductW)
     261                    {
     262                        MSIHANDLE hMsi = 0;
     263                        uRc = pfnMsiOpenProductW(wszProductCode, &hMsi);
     264                        if (uRc == 0)
     265                        {
     266                            static wchar_t const * const s_apwszProps[] =
     267                            {
     268                                INSTALLPROPERTY_INSTALLEDPRODUCTNAME,
     269                                INSTALLPROPERTY_PRODUCTNAME,
     270                                INSTALLPROPERTY_PACKAGENAME,
     271                            };
     272
     273                            wchar_t  wszProductName[1024];
     274                            DWORD    cwcProductName;
     275                            unsigned i = 0;
     276                            do
     277                            {
     278                                cwcProductName = RT_ELEMENTS(wszProductName) - 1;
     279                                uRc = pfnMsiGetProductPropertyW(hMsi, s_apwszProps[i], wszProductName, &cwcProductName);
     280                            }
     281                            while (   ++i < RT_ELEMENTS(s_apwszProps)
     282                                   && (   uRc != 0
     283                                       || cwcProductName < 2
     284                                       || cwcProductName >= RT_ELEMENTS(wszProductName)) );
     285                            uRc = pfnMsiCloseHandle(hMsi);
     286                            if (uRc == 0 && cwcProductName >= 2)
     287                            {
     288                                wszProductName[RT_MIN(cwcProductName, RT_ELEMENTS(wszProductName) - 1)] = '\0';
     289                                setError(hrcCaller,
     290                                         tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works.\n"
     291                                            "PSDispatch looks broken by the '%ls' (%ls) program, suspecting that it features the broken oleaut32.msm module as component %ls.\n"
     292                                            "\n"
     293                                            "We suggest you try uninstall '%ls'.\n"
     294                                            "\n"
     295                                            "See also https://support.microsoft.com/en-us/kb/316911 "),
     296                                         wszProductName, wszProductCode, wszComponentCode, wszProductName);
     297                                fSetError = true;
     298                            }
     299                        }
     300                    }
     301
     302                    /* MSI uses COM and may mess up our stuff. So, we wait with the fallback till afterwards in this case. */
     303                    if (!fSetError)
     304                    {
     305                        setError(hrcCaller,
     306                                 tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, CLSID_VirtualBox w/ IUnknown works.\n"
     307                                    "PSDispatch looks broken by installer %ls featuring the broken oleaut32.msm module as component %ls.\n"
     308                                    "\n"
     309                                    "See also https://support.microsoft.com/en-us/kb/316911 "),
     310                                 wszProductCode, wszComponentCode);
     311                        fSetError = true;
     312                    }
     313                }
     314            }
     315            if (!fSetError)
     316                setError(hrcCaller, tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, CLSID_VirtualBox w/ IUnknown works.\n"
     317                                       "PSDispatch looks broken by some installer featuring the broken oleaut32.msm module as a component.\n"
     318                                       "\n"
     319                                       "See also https://support.microsoft.com/en-us/kb/316911 "));
     320        }
     321        else if (lrc == ERROR_FILE_NOT_FOUND)
     322            setError(hrcCaller, tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works.\n"
     323                                   "PSDispatch looks fine. Weird"));
     324        else
     325            setError(hrcCaller, tr("Failed to instantiate CLSID_VirtualBox w/ IVirtualBox, but CLSID_VirtualBox w/ IUnknown works.\n"
     326                                   "Checking out PSDispatch registration ended with error: %u (%#x)"), lrc, lrc);
     327        RegCloseKey(hKey);
     328    }
     329
     330    pUnknown->Release();
     331    return hrcCaller;
     332}
     333#endif /* RT_OS_WINDOWS */
    158334
    159335/**
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