HRESULT GetTokenFromPublicKey(SBuffer &publicKeyBLOB, SBuffer &publicKeyTokenBLOB) { HRESULT hr = S_OK; BINDER_LOG_ENTER(W("GetTokenFromPublicKey")); const BYTE *pByteKey = publicKeyBLOB; DWORD dwKeyLen = publicKeyBLOB.GetSize(); BYTE *pByteToken = NULL; DWORD dwTokenLen = 0; if (!StrongNameTokenFromPublicKey(const_cast<BYTE *>(pByteKey), dwKeyLen, &pByteToken, &dwTokenLen)) { BINDER_LOG(W("StrongNameTokenFromPublicKey failed!")); IF_FAIL_GO(StrongNameErrorInfo()); } else { _ASSERTE(pByteToken != NULL); publicKeyTokenBLOB.Set(pByteToken, dwTokenLen); StrongNameFreeBuffer(pByteToken); } Exit: BINDER_LOG_LEAVE_HR(W("GetTokenFromPublicKey"), hr); return hr; }
FCIMPLEND FCIMPL1(Object*, AssemblyNameNative::GetPublicKeyToken, Object* refThisUNSAFE) { FCALL_CONTRACT; OBJECTREF orOutputArray = NULL; OBJECTREF refThis = (OBJECTREF) refThisUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_1(refThis); if (refThis == NULL) COMPlusThrow(kNullReferenceException, W("NullReference_This")); ASSEMBLYNAMEREF orThis = (ASSEMBLYNAMEREF)refThis; U1ARRAYREF orPublicKey = orThis->GetPublicKey(); if (orPublicKey != NULL) { DWORD cb = orPublicKey->GetNumComponents(); StrongNameBufferHolder<BYTE> pbToken; if (cb) { CQuickBytes qb; BYTE *pbKey = (BYTE*) qb.AllocThrows(cb); memcpy(pbKey, orPublicKey->GetDataPtr(), cb); { GCX_PREEMP(); if (!StrongNameTokenFromPublicKey(pbKey, cb, &pbToken, &cb)) COMPlusThrowHR(StrongNameErrorInfo()); } } Security::CopyEncodingToByteArray(pbToken, cb, &orOutputArray); } HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(orOutputArray); }
HRESULT AssemblySpec::LoadAssembly(Assembly** ppAssembly, OBJECTREF* pThrowable, /*= NULL*/ OBJECTREF* pExtraEvidence, /*= NULL*/ BOOL fPolicyLoad) /*= FALSE*/ { IAssembly* pIAssembly = NULL; HRESULT hr; Assembly *pAssembly = GetAppDomain()->FindCachedAssembly(this); if(pAssembly) { if ((pExtraEvidence != NULL) && (*pExtraEvidence != NULL)) IfFailGo(SECURITY_E_INCOMPATIBLE_EVIDENCE); *ppAssembly = pAssembly; return S_FALSE; } PEFile *pFile; IfFailGo(GetAppDomain()->BindAssemblySpec(this, &pFile, &pIAssembly, &pAssembly, pExtraEvidence, pThrowable)); // Loaded by AssemblyResolve event handler if (hr == S_FALSE) { //If loaded by the AssemblyResolve event, check that // the public keys are the same as in the AR. // However, if the found assembly is a dynamically // created one, security has decided to allow it. if (m_cbPublicKeyOrToken && pAssembly->m_pManifestFile) { if (!pAssembly->m_cbPublicKey) IfFailGo(FUSION_E_PRIVATE_ASM_DISALLOWED); // Ref has the full key if (m_dwFlags & afPublicKey) { if ((m_cbPublicKeyOrToken != pAssembly->m_cbPublicKey) || memcmp(m_pbPublicKeyOrToken, pAssembly->m_pbPublicKey, m_cbPublicKeyOrToken)) IfFailGo(FUSION_E_REF_DEF_MISMATCH); } // Ref has a token else if (pAssembly->m_cbRefedPublicKeyToken) { if ((m_cbPublicKeyOrToken != pAssembly->m_cbRefedPublicKeyToken) || memcmp(m_pbPublicKeyOrToken, pAssembly->m_pbRefedPublicKeyToken, m_cbPublicKeyOrToken)) IfFailGo(FUSION_E_REF_DEF_MISMATCH); } else { if (!StrongNameTokenFromPublicKey(pAssembly->m_pbPublicKey, pAssembly->m_cbPublicKey, &pAssembly->m_pbRefedPublicKeyToken, &pAssembly->m_cbRefedPublicKeyToken)) IfFailGo(StrongNameErrorInfo()); if ((m_cbPublicKeyOrToken != pAssembly->m_cbRefedPublicKeyToken) || memcmp(m_pbPublicKeyOrToken, pAssembly->m_pbRefedPublicKeyToken, m_cbPublicKeyOrToken)) IfFailGo(FUSION_E_REF_DEF_MISMATCH); } } *ppAssembly = pAssembly; return S_OK; } // Until we can create multiple Assembly objects for a single HMODULE // we can only store one IAssembly* per Assembly. It is very important // to maintain the IAssembly* for an image that is in the load-context. // An Assembly in the load-from-context can bind to an assembly in the // load-context but not visa-versa. Therefore, if we every get an IAssembly // from the load-from-context we must make sure that it will never be // found using a load. If it did then we could end up with Assembly dependencies // that are wrong. For example, if I do a LoadFrom() on an assembly in the GAC // and it requires another Assembly that I have preloaded in the load-from-context // then that dependency gets burnt into the Jitted code. Later on a Load() is // done on the assembly in the GAC and we single instance it back to the one // we have gotten from the load-from-context because the HMODULES are the same. // Now the dependency is wrong because it would not have the preloaded assembly // if the order was reversed. if (pIAssembly) { IFusionLoadContext *pLoadContext; hr = pIAssembly->GetFusionLoadContext(&pLoadContext); _ASSERTE(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { if (pLoadContext->GetContextType() == LOADCTX_TYPE_LOADFROM) { mdAssembly mda; if (FAILED(pFile->GetMDImport()->GetAssemblyFromScope(&mda))) { hr = COR_E_ASSEMBLYEXPECTED; goto exit; } LPCUTF8 psName; PBYTE pbPublicKey; DWORD cbPublicKey; AssemblyMetaDataInternal context; DWORD dwFlags; pFile->GetMDImport()->GetAssemblyProps(mda, (const void**) &pbPublicKey, &cbPublicKey, NULL, // hash alg &psName, &context, &dwFlags); AssemblySpec spec; if (FAILED(hr = spec.Init(psName, &context, pbPublicKey, cbPublicKey, dwFlags))) goto exit; IAssemblyName* pFoundAssemblyName; if (FAILED(hr = spec.CreateFusionName(&pFoundAssemblyName, FALSE))) goto exit; AssemblySink* pFoundSink = GetAppDomain()->GetAssemblySink(); if(!pFoundSink) { pFoundAssemblyName->Release(); hr = E_OUTOFMEMORY; goto exit; } IAssembly *pFoundIAssembly; BEGIN_ENSURE_PREEMPTIVE_GC(); hr = FusionBind::GetAssemblyFromFusion(GetAppDomain()->GetFusionContext(), pFoundSink, pFoundAssemblyName, &spec.m_CodeInfo, &pFoundIAssembly); if(SUCCEEDED(hr)) { DWORD dwFoundSize = MAX_PATH; WCHAR wszFoundPath[MAX_PATH]; // Get the path to the module containing the manifest if (SUCCEEDED(pFoundIAssembly->GetManifestModulePath(wszFoundPath, &dwFoundSize))) { // Keep the default context's IAssembly if the paths are the same if (!_wcsicmp(wszFoundPath, pFile->GetFileName())) { pIAssembly->Release(); pIAssembly = pFoundIAssembly; // Make sure the new IAssembly isn't holding its own refcount on // the file (we've just verified we're holding the same file.) // Otherwise we will leak the handle when we unload the assembly, // assuming fusion decides to cache this IAssembly pointer // somewhere internally. PEFile::ReleaseFusionMetadataImport(pFoundIAssembly); } else pFoundIAssembly->Release(); } } pFoundAssemblyName->Release(); pFoundSink->Release(); END_ENSURE_PREEMPTIVE_GC(); hr = S_OK; } exit: pLoadContext->Release(); } } // Create the assembly and delay loading the main module. Module* pModule; hr = GetAppDomain()->LoadAssembly(pFile, pIAssembly, &pModule, &pAssembly, pExtraEvidence, fPolicyLoad, pThrowable); BEGIN_ENSURE_PREEMPTIVE_GC(); if(SUCCEEDED(hr)) { *ppAssembly = pAssembly; /*HRESULT hrLoose =*/ GetAppDomain()->AddAssemblyToCache(this, pAssembly); } if(pIAssembly) pIAssembly->Release(); END_ENSURE_PREEMPTIVE_GC(); ErrExit: if (FAILED(hr) && (pThrowable!=NULL)) { BEGIN_ENSURE_COOPERATIVE_GC(); if ((pThrowable != RETURN_ON_ERROR) && (*pThrowable == NULL)) { if (m_pAssemblyName) PostFileLoadException(m_pAssemblyName, FALSE,NULL, hr, pThrowable); else { MAKE_UTF8PTR_FROMWIDE(szName, m_CodeInfo.m_pszCodeBase); PostFileLoadException(szName, TRUE,NULL, hr, pThrowable); } } END_ENSURE_COOPERATIVE_GC(); } return hr; }