HRESULT GetCLRRuntimeInfoHelper()

in inc/clr/extra/LegacyActivationShimUtil.h [629:770]


        HRESULT GetCLRRuntimeInfoHelper(
            /*out*/ ICLRRuntimeInfo **ppCLRRuntimeInfo,
            LPCWSTR  pEXE = NULL,
            IStream *pIStream = NULL,
            __inout_ecount_opt(*pcchVersion) LPWSTR wszVersion = NULL,
            DWORD   *pcchVersion = NULL,
            __out_ecount_opt(*pcchImageVersion) LPWSTR wszImageVersion = NULL,
            DWORD   *pcchImageVersion = NULL)
        {
            HRESULT hr = S_OK;

            //
            // 1. Try policy-based binding first, which will incorporate config files and such.
            //

            ICLRMetaHostPolicy *pMetaHostPolicy = NULL;
            IfHrFailRet(GetCLRMetaHostPolicy(&pMetaHostPolicy));

            DWORD dwConfigFlags = 0;

            hr = pMetaHostPolicy->GetRequestedRuntime(
                METAHOST_POLICY_USE_PROCESS_IMAGE_PATH,
                pEXE,
                pIStream,
                wszVersion,
                pcchVersion,
                wszImageVersion,
                pcchImageVersion,
                &dwConfigFlags,
                IID_ICLRRuntimeInfo,
                reinterpret_cast<LPVOID *>(ppCLRRuntimeInfo));

            if (hr != S_OK &&
                pEXE == NULL &&
                pIStream == NULL &&
                wszVersion == NULL)
            {   //
                // 2. Try to bind using ICLRMetaHostPolicy::GetRequestedRuntime and "v4.0.0" and upgrade policy.
                //

                WCHAR _wszVersion[256];  // We can't use new in this header, so just pick an obscenely long version string length of 256
                DWORD _cchVersion = countof(_wszVersion);
                wcscpy_s(_wszVersion, _cchVersion, L"v4.0.0");
                hr = pMetaHostPolicy->GetRequestedRuntime(
                    static_cast<METAHOST_POLICY_FLAGS>(METAHOST_POLICY_USE_PROCESS_IMAGE_PATH |
                                                       METAHOST_POLICY_APPLY_UPGRADE_POLICY),
                    pEXE,
                    pIStream, // (is NULL)
                    _wszVersion,
                    &_cchVersion,
                    wszImageVersion,
                    pcchImageVersion,
                    &dwConfigFlags,
                    IID_ICLRRuntimeInfo,
                    reinterpret_cast<LPVOID *>(ppCLRRuntimeInfo));
            }

            if (hr != S_OK &&
                pEXE == NULL &&
                pIStream == NULL &&
                wszVersion == NULL)
            {   //
                // 3. Try to bind using GetRequestedRuntimeInfo(NULL)
                //

                typedef HRESULT __stdcall GetRequestedRuntimeInfo_t(
                    LPCWSTR pExe,
                    LPCWSTR pwszVersion,
                    LPCWSTR pConfigurationFile,
                    DWORD startupFlags,
                    DWORD runtimeInfoFlags,
                    LPWSTR pDirectory,
                    DWORD dwDirectory,
                    DWORD *dwDirectoryLength,
                    LPWSTR pVersion,
                    DWORD cchBuffer,
                    DWORD* dwlength);

                HMODULE hMscoree = NULL;
                IfHrFailRet(GetMSCOREE(&hMscoree));

                // We're using GetRequestedRuntimeInfo here because it is the only remaining API
                // that will not be Whidbey-capped and will allow "bind to latest" semantics. This
                // is cheating a bit, but should work for now. The alternative is to use
                // ICLRMetaHost::EnumerateRuntimes to achieve the same result.
                DelayLoadFunctor<GetRequestedRuntimeInfo_t> GetRequestedRuntimeInfoFN;
                IfHrFailRet(GetRequestedRuntimeInfoFN.Init(hMscoree, "GetRequestedRuntimeInfo"));

                WCHAR szDir_[_MAX_PATH];
                DWORD cchDir_ = countof(szDir_);
                WCHAR szVersion_[_MAX_PATH];
                DWORD cchVersion_ = countof(szVersion_);
                DWORD dwInfoFlags_ = RUNTIME_INFO_UPGRADE_VERSION
                                   | RUNTIME_INFO_DONT_SHOW_ERROR_DIALOG;

                IfHrFailRet(GetRequestedRuntimeInfoFN()(
                    NULL,
                    NULL,
                    NULL,
                    0,
                    dwInfoFlags_,
                    szDir_,
                    cchDir_,
                    &cchDir_,
                    szVersion_,
                    cchVersion_,
                    &cchVersion_));

                // Unable to get a version to try to load.
                if (hr != S_OK)
                {
                    return CLR_E_SHIM_RUNTIMELOAD;
                }

                ICLRMetaHost *pMetaHost = NULL;
                IfHrFailRet(GetCLRMetaHost(&pMetaHost));

                hr = pMetaHost->GetRuntime(szVersion_,
                                           IID_ICLRRuntimeInfo,
                                           reinterpret_cast<LPVOID *>(ppCLRRuntimeInfo));

                if (hr != S_OK)
                {
                    return CLR_E_SHIM_RUNTIMELOAD;
                }

                if (wszImageVersion != NULL)
                {
                    wcsncpy_s(wszImageVersion, *pcchImageVersion, szVersion_, cchVersion_);
                    *pcchImageVersion = cchVersion_;
                }
            }

            if (hr == S_OK &&
                (dwConfigFlags & METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK) ==
                METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE)
            {   // If the config requested that the runtime be bound as the legacy runtime.
                IfHrFailRet((*ppCLRRuntimeInfo)->BindAsLegacyV2Runtime());
            }

            return hr;
        }