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;
}