Ejemplo n.º 1
0
HRESULT FusionBind::LoadAssembly(IApplicationContext* pFusionContext,
                                 IAssembly** ppFusionAssembly)
{
    HRESULT hr;

    TIMELINE_START(FUSIONBIND, ("LoadAssembly %s", m_pAssemblyName));

    IAssemblyName* pFusionAssemblyName = NULL;    

    IfFailGo(CreateFusionName(&pFusionAssemblyName));

    hr = GetAssemblyFromFusion(pFusionContext,
                               NULL,
                               pFusionAssemblyName,
                               &m_CodeInfo,
                               ppFusionAssembly);

 ErrExit:
    if(pFusionAssemblyName)
        pFusionAssemblyName->Release();

    TIMELINE_END(FUSIONBIND, ("LoadAssembly %s", m_pAssemblyName));

    return hr;
}
Ejemplo n.º 2
0
HRESULT FusionBind::CreateFusionContext(LPCWSTR pzName, IApplicationContext** ppFusionContext)
{
    TIMELINE_START(FUSIONBIND, ("CreateFusionContext %S", pzName));

    _ASSERTE(ppFusionContext);
    
    // This is a file name not a namespace
    LPCWSTR contextName = NULL;

    if(pzName) {
        contextName = wcsrchr( pzName, L'\\' );
        if(contextName)
            contextName++;
        else
            contextName = pzName;
    }

    // We go off and create a fusion context for this application domain.
    // Note, once it is made it can not be modified.
    IAssemblyName *pFusionAssemblyName = NULL;
    HRESULT hr = CreateAssemblyNameObject(&pFusionAssemblyName, contextName, 0, NULL);

    if(SUCCEEDED(hr)) {
        hr = CreateApplicationContext(pFusionAssemblyName, ppFusionContext);
        pFusionAssemblyName->Release();
    }

    if(pzName)
        TIMELINE_END(FUSIONBIND, ("CreateFusionContext %S", pzName));
    else
        TIMELINE_END(FUSIONBIND, ("CreateFusionContext <unknown>"));

    return hr;
}
Ejemplo n.º 3
0
HRESULT FusionBind::ParseName()
{
    HRESULT hr = S_OK;

    if (m_fParsed || !m_pAssemblyName)
        return S_OK;

    TIMELINE_START(FUSIONBIND, ("ParseName %s", m_pAssemblyName));

    IAssemblyName *pName;

    CQuickBytes qb;
    long pwNameLen = WszMultiByteToWideChar(CP_UTF8, 0, m_pAssemblyName, -1, 0, 0);
    LPWSTR pwName = (LPWSTR) qb.Alloc(pwNameLen*sizeof(WCHAR));

    WszMultiByteToWideChar(CP_UTF8, 0, m_pAssemblyName, -1, pwName, pwNameLen); 
    IfFailRet(CreateAssemblyNameObject(&pName, pwName, CANOF_PARSE_DISPLAY_NAME, NULL));

    if (m_ownedFlags & NAME_OWNED)
        delete [] m_pAssemblyName;
    m_pAssemblyName = NULL;

    hr = Init(pName);

    pName->Release();

    TIMELINE_END(FUSIONBIND, ("ParseName %s", m_pAssemblyName));

    return hr;
}
Ejemplo n.º 4
0
HRESULT AssemblySpec::InitializeSpec(mdToken kAssemblyRef, IMDInternalImport *pImport, Assembly* pAssembly)
{
    HRESULT hr = S_OK;

    m_fParsed = TRUE;
    DWORD rid = RidFromToken(kAssemblyRef);
    if((rid == 0)||(rid > pImport->GetCountWithTokenKind(mdtAssemblyRef))) {
        BAD_FORMAT_ASSERT(!"AssemblyRef Token Out of Range");
        return COR_E_BADIMAGEFORMAT;
    }
    // Hash algorithm used to find this hash is saved in Assembly def
    pImport->GetAssemblyRefProps(kAssemblyRef,                          // [IN] The AssemblyRef for which to get the properties.        
                                 (const void**) &m_pbPublicKeyOrToken,  // [OUT] Pointer to the public key or token.                        
                                 &m_cbPublicKeyOrToken,                 // [OUT] Count of bytes in the public key or token.                 
                                 &m_pAssemblyName,                      // [OUT] Buffer to fill with name.                              
                                 &m_context,                            // [OUT] Assembly MetaData.                                     
                                 NULL,        // [OUT] Hash blob.                                             
                                 NULL,                        // [OUT] Count of bytes in the hash blob.                       
                                 &m_dwFlags);                           // [OUT] Flags.          

    if ((!m_pAssemblyName) ||
        (*m_pAssemblyName == 0)) {
        BAD_FORMAT_ASSERT(!"NULL AssemblyRef Name");
        return COR_E_BADIMAGEFORMAT;
    }

    MAKE_WIDEPTR_FROMUTF8(pwName,m_pAssemblyName);

    if (wcschr(pwName,'\\') 
        || wcschr(pwName,'/') 
        || wcschr(pwName,':')
        || (RunningOnWin95() && ContainsUnmappableANSIChars(pwName))) {
        BAD_FORMAT_ASSERT(!"Bad AssemblyRef Name");
        return COR_E_BADIMAGEFORMAT;
    }

    if((!m_pbPublicKeyOrToken) && (m_cbPublicKeyOrToken != 0)) {
        BAD_FORMAT_ASSERT(!"NULL Public Key or Token of AssemblyRef");
        return COR_E_BADIMAGEFORMAT;
    }


    // Let's get the CodeBase from the caller and use it as a hint
    if(pAssembly && (!pAssembly->IsShared()))
        m_CodeInfo.SetParentAssembly(pAssembly->GetFusionAssembly());

#if defined(_DEBUG) && defined(FUSION_SUPPORTED)
    {
        // Test fusion conversion
        IAssemblyName *pFusionName;
        _ASSERTE(CreateFusionName(&pFusionName, TRUE) == S_OK);
        AssemblySpec testFusion;
        _ASSERTE(testFusion.InitializeSpec(pFusionName) == S_OK);
        pFusionName->Release();
    }
#endif // _DEBUG && FUSION_SUPPORTED

    return hr;
}
Ejemplo n.º 5
0
HRESULT FusionBind::CreateFusionName(IAssemblyName **ppName, BOOL fIncludeHash)
{
    TIMELINE_START(FUSIONBIND, ("CreateFusionName %s", m_pAssemblyName));

    HRESULT hr;
    IAssemblyName *pFusionAssemblyName = NULL;
    LPWSTR pwAssemblyName = NULL;
    CQuickBytes qb;

    if (m_pAssemblyName) {
        long pwNameLen = WszMultiByteToWideChar(CP_UTF8, 0, m_pAssemblyName, -1, 0, 0);
        pwAssemblyName = (LPWSTR) qb.Alloc(pwNameLen*sizeof(WCHAR));

        WszMultiByteToWideChar(CP_UTF8, 0, m_pAssemblyName, -1, pwAssemblyName, pwNameLen);
    }

    IfFailGo(CreateAssemblyNameObject(&pFusionAssemblyName, pwAssemblyName, 
                                      m_fParsed || (!pwAssemblyName) ? 0 : CANOF_PARSE_DISPLAY_NAME, NULL));


    if (m_fParsed) {
        if (m_context.usMajorVersion != (USHORT) -1) {
            IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_MAJOR_VERSION, 
                                                      &m_context.usMajorVersion, 
                                                      sizeof(USHORT)));
            
            if (m_context.usMinorVersion != (USHORT) -1) {
                IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_MINOR_VERSION, 
                                                          &m_context.usMinorVersion, 
                                                          sizeof(USHORT)));
                
                if (m_context.usBuildNumber != (USHORT) -1) {
                    IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_BUILD_NUMBER, 
                                                              &m_context.usBuildNumber, 
                                                              sizeof(USHORT)));
                    
                    if (m_context.usRevisionNumber != (USHORT) -1)
                        IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_REVISION_NUMBER, 
                                                                  &m_context.usRevisionNumber, 
                                                                  sizeof(USHORT)));
                }
            }
        }
        
        if (m_context.szLocale) {
            MAKE_WIDEPTR_FROMUTF8(pwLocale,m_context.szLocale);
            
            IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_CULTURE, 
                                                      pwLocale, 
                                                      (DWORD)(wcslen(pwLocale) + 1) * sizeof (WCHAR)));
        }
        
        if (m_pbPublicKeyOrToken) {
            if (m_cbPublicKeyOrToken) {
                if(m_dwFlags & afPublicKey) {
                    IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_PUBLIC_KEY,
                                                              m_pbPublicKeyOrToken, m_cbPublicKeyOrToken));
                }
                else {
                        IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN,
                                                                  m_pbPublicKeyOrToken, m_cbPublicKeyOrToken));
                }
            }
            else {
                IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_NULL_PUBLIC_KEY_TOKEN,
                                                          NULL, 0));
            }
        }
    }

    if (m_CodeInfo.m_dwCodeBase > 0) {
        IfFailGo(pFusionAssemblyName->SetProperty(ASM_NAME_CODEBASE_URL,
                                                  (void*)m_CodeInfo.m_pszCodeBase, 
                                                  m_CodeInfo.m_dwCodeBase*sizeof(WCHAR)));
    }

    *ppName = pFusionAssemblyName;

    TIMELINE_END(FUSIONBIND, ("CreateFusionName %s", m_pAssemblyName));

    return S_OK;

 ErrExit:
    if (pFusionAssemblyName)
        pFusionAssemblyName->Release();

    TIMELINE_END(FUSIONBIND, ("CreateFusionName %s", m_pAssemblyName));

    return hr;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
HRESULT AssemblySpec::GetAssemblyFromFusion(AppDomain* pAppDomain,
                                            IAssemblyName* pFusionAssemblyName,
                                            CodeBaseInfo* pCodeBase,
                                            IAssembly** ppFusionAssembly,
                                            PEFile** ppFile,
                                            CQuickWSTR* pFusionLog,
                                            OBJECTREF* pExtraEvidence,
                                            OBJECTREF* pThrowable)
{
    _ASSERTE(ppFile);
    HRESULT hr = S_OK;
    IAssembly *pFusionAssembly = NULL;

    COMPLUS_TRY {
        DWORD dwSize = MAX_PATH;
        CQuickWSTR bufferPath;
        WCHAR *pPath = NULL;
        AssemblySink* pSink;
        DWORD eLocation;

        CQuickWSTR bufferCodebase;
        LPWSTR pwsCodeBase = NULL;
        DWORD  dwCodeBase = 0;
        IAssemblyName *pNameDef = NULL;
        
        IApplicationContext *pFusionContext = pAppDomain->GetFusionContext();
        pSink = pAppDomain->GetAssemblySink();
        if(!pSink) {
            hr = E_OUTOFMEMORY;
            COMPLUS_LEAVE;
        }
        
        pSink->pFusionLog=pFusionLog;
        hr = FusionBind::GetAssemblyFromFusion(pFusionContext,
                                               pSink,
                                               pFusionAssemblyName,
                                               pCodeBase,
                                               &pFusionAssembly);
        pSink->pFusionLog=NULL;
        if(SUCCEEDED(hr)) {
            _ASSERTE(pFusionAssembly);

            // Get the path to the module containing the manifest
            dwSize = bufferPath.MaxSize();
            pPath = bufferPath.Ptr();
            hr = pFusionAssembly->GetManifestModulePath(pPath,
                                                        &dwSize);
            if(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
                pPath = bufferPath.Alloc(dwSize);
                if (pPath == NULL) {
                    hr = E_OUTOFMEMORY;
                    COMPLUS_LEAVE;
                }
                hr = pFusionAssembly->GetManifestModulePath(pPath,
                                                        &dwSize);
            }

            if(SUCCEEDED(hr)) {
                hr = pFusionAssembly->GetAssemblyNameDef(&pNameDef);
                if (SUCCEEDED(hr)) {
                    dwCodeBase = bufferCodebase.MaxSize();
                    pwsCodeBase = bufferCodebase.Ptr();
                    hr = pNameDef->GetProperty(ASM_NAME_CODEBASE_URL, pwsCodeBase, &dwCodeBase);
                    if(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)) {
                        pwsCodeBase = bufferCodebase.Alloc(dwCodeBase);
                        if (pwsCodeBase == NULL) {
                            hr = E_OUTOFMEMORY;
                            COMPLUS_LEAVE;
                        }
                        hr = pNameDef->GetProperty(ASM_NAME_CODEBASE_URL, pwsCodeBase, &dwCodeBase);
                    }
                    pNameDef->Release();
                }
            }
        }
        pSink->Release();

        if(hr == S_OK && dwSize) {
            // See if we need to perform a strong name verification.
            hr = pFusionAssembly->GetAssemblyLocation(&eLocation);


            if (SUCCEEDED(hr)) {
                switch ((eLocation & ASMLOC_LOCATION_MASK)) {
                case ASMLOC_GAC:
                case ASMLOC_DOWNLOAD_CACHE:
                case ASMLOC_UNKNOWN:
                    // Assemblies from the GAC or download cache have
                    // already been verified by Fusion. Location Unknown
                    // indicates a load from the dev path, which we'll
                    // assume isn't a interesting case for verification.
                    hr = S_OK;
                    break;
                case ASMLOC_RUN_FROM_SOURCE:
                    // For now, just verify these every time, we need to
                    // cache the fact that at least one verification has
                    // been performed (if strong name policy permits
                    if (SUCCEEDED(hr)&&(eLocation&ASMLOC_CODEBASE_HINT))
                    {
                        hr=CheckFileAccess(pPath,FILE_READ_DATA);
                        if (FAILED(hr))
                            break;
                    }
                    // caching of verification results).
                    if (StrongNameSignatureVerification(pPath,
                                                        SN_INFLAG_INSTALL|SN_INFLAG_ALL_ACCESS|SN_INFLAG_RUNTIME,
                                                        NULL))
                        hr = S_OK;
                    else {
                        hr = StrongNameErrorInfo();
                        if (hr == CORSEC_E_MISSING_STRONGNAME)
                            hr = S_OK;
                        else
                            hr = CORSEC_E_INVALID_STRONGNAME;
                    }
                    break;
                default:
                    _ASSERTE(FALSE);
                }
                if (SUCCEEDED(hr)) {
                    hr = SystemDomain::LoadFile(pPath, 
                                                NULL, 
                                                mdFileNil, 
                                                FALSE, 
                                                pFusionAssembly, 
                                                pwsCodeBase,
                                                pExtraEvidence,
                                                ppFile,
                                                FALSE);
                    if (SUCCEEDED(hr)) {
                        if(ppFusionAssembly) {
                            pFusionAssembly->AddRef();
                            *ppFusionAssembly = pFusionAssembly;
                        }
                        if((eLocation & ASMLOC_LOCATION_MASK) == ASMLOC_GAC)
                            // Assemblies in the GAC have also had any internal module
                            // hashes verified at install time.
                            (*ppFile)->SetHashesVerified();
                    }
                }
            }
            else if (hr == E_NOTIMPL) {
                // process exe
                _ASSERTE(pAppDomain == SystemDomain::System()->DefaultDomain());
                hr = PEFile::Clone(SystemDomain::System()->DefaultDomain()->m_pRootFile, ppFile);
                if(SUCCEEDED(hr) && ppFusionAssembly) {
                    pFusionAssembly->AddRef();
                    *ppFusionAssembly = pFusionAssembly;
                }
            }
        }
    }
    COMPLUS_CATCH {
        BEGIN_ENSURE_COOPERATIVE_GC();
        if (pThrowable) 
        {
            *pThrowable = GETTHROWABLE();
            hr = SecurityHelper::MapToHR(*pThrowable);
        }
        else
            hr = SecurityHelper::MapToHR(GETTHROWABLE());
        END_ENSURE_COOPERATIVE_GC();
    } COMPLUS_END_CATCH
 
    if (pFusionAssembly)
        pFusionAssembly->Release();

    return hr;
}
Ejemplo n.º 8
0
HRESULT AssemblySpec::LowLevelLoadManifestFile(PEFile** ppFile,
                                               IAssembly** ppIAssembly,
                                               Assembly **ppDynamicAssembly,
                                               OBJECTREF* pExtraEvidence,
                                               OBJECTREF* pThrowable)
{
    CANNOTTHROWCOMPLUSEXCEPTION();

    HRESULT hr = S_OK;
    IAssemblyName* pFusionAssemblyName = NULL;     // Assembly object to assembly in fusion cache

    if(!(m_pAssemblyName || m_CodeInfo.m_pszCodeBase)) {
        PostFileLoadException("", FALSE, NULL, COR_E_FILENOTFOUND, pThrowable);
        return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
    }

    //
    // Check to see if this fits our rather loose idea of a reference to mscorlib.
    // If so, don't use fusion to bind it - do it ourselves.
    //

    if (IsMscorlib())
    {
        _ASSERTE(wcslen(SystemDomain::System()->BaseLibrary()) > 0);
        hr = PEFile::Create(SystemDomain::System()->BaseLibrary(), 
                            NULL, 
                            mdFileNil, 
                            TRUE, 
                            NULL, 
                            NULL, // Code base is the same as the name
                            NULL, // Extra Evidence
                            ppFile);
        _ASSERTE((*ppFile)->IsSystem());
        if (ppDynamicAssembly) *ppDynamicAssembly = NULL;
        return hr;
    }

    CQuickWSTR FusionLog;
    FusionLog.Ptr()[0]=L'\0';

    BEGIN_ENSURE_PREEMPTIVE_GC();

    Assembly *pAssembly = NULL;
    PEFile *pFile = NULL;

    hr = CreateFusionName(&pFusionAssemblyName);
    if (FAILED(hr))
        goto exit;

    hr = pFusionAssemblyName->SetProperty(ASM_NAME_NULL_CUSTOM,NULL,0); //do not look in ZAP
    if (FAILED(hr))
        goto exit;

    hr = GetAssemblyFromFusion(GetAppDomain(),
                               pFusionAssemblyName,
                               &m_CodeInfo,
                               ppIAssembly,
                               &pFile,
                               &FusionLog,
                               pExtraEvidence,
                               pThrowable);
    if(FAILED(hr)) {

            DWORD cb = 0;
            pFusionAssemblyName->GetDisplayName(NULL, &cb, 0);
            if(cb) {
                CQuickBytes qb;
                LPWSTR pwsFullName = (LPWSTR) qb.Alloc(cb*sizeof(WCHAR));

                if (SUCCEEDED(pFusionAssemblyName->GetDisplayName(pwsFullName, &cb, 0))) {
                if ((pAssembly = GetAppDomain()->RaiseAssemblyResolveEvent(pwsFullName, pThrowable)) != NULL) {
                        pFile = pAssembly->GetManifestFile();
                        hr = S_FALSE;
                    }
                }
            }

#ifdef _DEBUG
        if(FAILED(hr)) {
            if (m_pAssemblyName)
                LOG((LF_CLASSLOADER, LL_ERROR, "Fusion could not load from full name, %s\n", m_pAssemblyName));
            else if (m_CodeInfo.m_pszCodeBase)
                LOG((LF_CLASSLOADER, LL_ERROR, "Fusion could not load from codebase, %s\n",m_CodeInfo.m_pszCodeBase));
            else
                LOG((LF_CLASSLOADER, LL_ERROR, "Fusion could not load unknown assembly.\n"));
        }
#endif //_DEBUG

    }

 exit:
    if (SUCCEEDED(hr)) {
        if (ppFile) *ppFile = pFile;
        if (ppDynamicAssembly) *ppDynamicAssembly = pAssembly;
    }

    if(pFusionAssemblyName)
        pFusionAssemblyName->Release();

    END_ENSURE_PREEMPTIVE_GC();

    if (FAILED(hr)) {
        if (m_pAssemblyName)
            PostFileLoadException(m_pAssemblyName, FALSE,FusionLog.Ptr(), hr, pThrowable);
        else {
            MAKE_UTF8PTR_FROMWIDE(szName, m_CodeInfo.m_pszCodeBase);
            PostFileLoadException(szName, TRUE,FusionLog.Ptr(), hr, pThrowable);
        }
    }

    return hr;
}
Ejemplo n.º 9
0
void    AsmMan::EndAssembly()
{
    if(m_pCurAsmRef)
    {
        if(m_pCurAsmRef->isRef)
        { // list the assembly ref
            if(GetAsmRefByName(m_pCurAsmRef->szAlias))
            {
                //report->warn("Multiple declarations of Assembly Ref '%s', ignored except the 1st one\n",m_pCurAsmRef->szName);
                delete m_pCurAsmRef;
                m_pCurAsmRef = NULL;
                return;
            }
            if(m_pCurAsmRef->isAutodetect)
            {
                IAssemblyName* pIAsmName;
                HRESULT hr;
                // Convert name to Unicode
                WszMultiByteToWideChar(g_uCodePage,0,m_pCurAsmRef->szName,-1,wzUniBuf,dwUniBuf);
                hr = CreateAssemblyNameObject(&pIAsmName,wzUniBuf,CANOF_PARSE_DISPLAY_NAME,NULL);
                if(SUCCEEDED(hr))
                {
                    // set enumeration criteria: what is known about AsmRef (besides name)
                    if(m_pCurAsmRef->usVerMajor != (USHORT)0xFFFF)
                        pIAsmName->SetProperty(ASM_NAME_MAJOR_VERSION,&(m_pCurAsmRef->usVerMajor),2);
                    if(m_pCurAsmRef->usVerMinor != (USHORT)0xFFFF)
                        pIAsmName->SetProperty(ASM_NAME_MINOR_VERSION,&(m_pCurAsmRef->usVerMinor),2);
                    if(m_pCurAsmRef->usBuild != (USHORT)0xFFFF)
                        pIAsmName->SetProperty(ASM_NAME_BUILD_NUMBER,&(m_pCurAsmRef->usBuild),2);
                    if(m_pCurAsmRef->usRevision != (USHORT)0xFFFF)
                        pIAsmName->SetProperty(ASM_NAME_REVISION_NUMBER,&(m_pCurAsmRef->usRevision),2);
                    if(m_pCurAsmRef->pPublicKeyToken)
                        pIAsmName->SetProperty(ASM_NAME_PUBLIC_KEY_TOKEN,
                                               m_pCurAsmRef->pPublicKeyToken->ptr(),
                                               m_pCurAsmRef->pPublicKeyToken->length());
                    if(m_pCurAsmRef->pLocale)
                        pIAsmName->SetProperty(ASM_NAME_CULTURE,
                                               m_pCurAsmRef->pLocale->ptr(),
                                               m_pCurAsmRef->pLocale->length());

                    // enumerate assemblies
                    IAssemblyEnum* pIAsmEnum = NULL;
                    hr = CreateAssemblyEnum(&pIAsmEnum, NULL, pIAsmName, ASM_CACHE_GAC, NULL);
                    if(SUCCEEDED(hr))
                    {
                        IAssemblyName* pIAsmNameFound;
                        IAssemblyName* pIAsmNameLatestVer = NULL;
                        ULONGLONG   ullVer=0, ullVerLatest=0;
                        DWORD  dwVerHi, dwVerLo;
    
                        // find the latest and greatest, if any
                        for(;;)
                        {
                            pIAsmNameFound = NULL;
                            hr = pIAsmEnum->GetNextAssembly(NULL,&pIAsmNameFound,0); 
                            if(SUCCEEDED(hr) && pIAsmNameFound)
                            {
    
                                pIAsmNameFound->GetVersion(&dwVerHi,&dwVerLo);
                                ullVer = (ULONGLONG)dwVerHi;
                                ullVer <<= sizeof(DWORD);
                                ullVer |= dwVerLo;
                                if(ullVer > ullVerLatest)
                                {
                                    if(pIAsmNameLatestVer)
                                       pIAsmNameLatestVer->Release(); 
                                    ullVerLatest = ullVer;
                                    pIAsmNameLatestVer = pIAsmNameFound;
                                }
                                else
                                    pIAsmNameFound->Release();
                            }
                            else break;
                        }
                        // if found, fill the gaps
                        if(pIAsmNameLatestVer)
                        {
                            DWORD cbSize=0;
                            USHORT usDummy=0;

                            if(m_pCurAsmRef->pPublicKeyToken == NULL)
                            {
                                cbSize = 1024;
                                pIAsmNameLatestVer->GetProperty(ASM_NAME_PUBLIC_KEY_TOKEN,
                                                wzUniBuf, &cbSize);
                                if(cbSize)
                                {
                                    if((m_pCurAsmRef->pPublicKeyToken = new BinStr()))
                                        memcpy(m_pCurAsmRef->pPublicKeyToken->getBuff(cbSize),
                                            wzUniBuf, cbSize);
                                }
                            }
    
                            if(m_pCurAsmRef->usVerMajor == (USHORT)0xFFFF)
                            {
                                cbSize = (DWORD)sizeof(WORD);
                                pIAsmNameLatestVer->GetProperty(ASM_NAME_MAJOR_VERSION,
                                                &usDummy, &cbSize);
                                m_pCurAsmRef->usVerMajor = usDummy;
                            }
                            if(m_pCurAsmRef->usVerMinor == (USHORT)0xFFFF)
                            {
                                cbSize = (DWORD)sizeof(WORD);
                                pIAsmNameLatestVer->GetProperty(ASM_NAME_MINOR_VERSION,
                                                &usDummy, &cbSize);
                                m_pCurAsmRef->usVerMinor = usDummy;
                            }
                            if(m_pCurAsmRef->usBuild == (USHORT)0xFFFF)
                            {
                                cbSize = (DWORD)sizeof(WORD);
                                pIAsmNameLatestVer->GetProperty(ASM_NAME_BUILD_NUMBER,
                                                &usDummy, &cbSize);
                                m_pCurAsmRef->usBuild = usDummy;
                            }
                            if(m_pCurAsmRef->usRevision == (USHORT)0xFFFF)
                            {
                                cbSize = (DWORD)sizeof(WORD);
                                pIAsmNameLatestVer->GetProperty(ASM_NAME_REVISION_NUMBER,
                                                &usDummy, &cbSize);
                                m_pCurAsmRef->usRevision = usDummy;
                            }
                            
                            if(m_pCurAsmRef->pLocale == NULL)
                            {
                                cbSize = 1024;
                                pIAsmNameLatestVer->GetProperty(ASM_NAME_CULTURE,
                                                wzUniBuf, &cbSize);

                                if(cbSize > (DWORD)sizeof(WCHAR))
                                {
                                    if((m_pCurAsmRef->pLocale = new BinStr()))
                                        memcpy(m_pCurAsmRef->pLocale->getBuff(cbSize),
                                            wzUniBuf, cbSize);
                                }
                            }
                            pIAsmNameLatestVer->Release(); 
                        }
                        else
                            report->warn("Failed to autodetect assembly '%s'\n",m_pCurAsmRef->szName);
                        // if no assembly found, leave it as is, it might be not a GAC assembly
    
                        pIAsmEnum->Release();
                    }
                    else
                        report->error("Failed to enum assemblies %S, hr=0x%08X\n",wzUniBuf,hr);
                    pIAsmName->Release();
                }
                else
                    report->error("Failed to create assembly name object for %S, hr=0x%08X\n",wzUniBuf,hr);
            } // end if isAutodetect
            m_AsmRefLst.PUSH(m_pCurAsmRef);
            m_pCurAsmRef->tkTok = TokenFromRid(m_AsmRefLst.COUNT(),mdtAssemblyRef);
        }
        else
        {
            HRESULT                 hr = S_OK;
            m_pCurAsmRef->tkTok = TokenFromRid(1,mdtAssembly);
            // Determine the strong name public key. This may have been set
            // via a directive in the source or from the command line (which
            // overrides the directive). From the command line we may have
            // been provided with a file or the name of a CAPI key
            // container. Either may contain a public key or a full key
            // pair.
            if (((Assembler*)m_pAssembler)->m_wzKeySourceName)
            {
                {
                    // Read public key or key pair from file.
                    HANDLE hFile = WszCreateFile(((Assembler*)m_pAssembler)->m_wzKeySourceName,
                                                 GENERIC_READ,
                                                 FILE_SHARE_READ,
                                                 NULL,
                                                 OPEN_EXISTING,
                                                 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
                                                 NULL);
                    if(hFile == INVALID_HANDLE_VALUE)
                    {
                        hr = GetLastError();
                        report->error("Failed to open key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr);
                        m_pCurAsmRef = NULL;
                        return;
                    }

                    // Determine file size and allocate an appropriate buffer.
                    m_sStrongName.m_cbPublicKey = SafeGetFileSize(hFile, NULL);
                    if (m_sStrongName.m_cbPublicKey == 0xffffffff) {
                        report->error("File size too large\n");
                        m_pCurAsmRef = NULL;
                        CloseHandle(hFile);
                        return;
                    }

                    m_sStrongName.m_pbPublicKey = new BYTE[m_sStrongName.m_cbPublicKey];
                    if (m_sStrongName.m_pbPublicKey == NULL) {
                        report->error("Failed to allocate key buffer\n");
                        m_pCurAsmRef = NULL;
                        CloseHandle(hFile);
                        return;
                    }
                    m_sStrongName.m_dwPublicKeyAllocated = 2;

                    // Read the file into the buffer.
                    DWORD dwBytesRead;
                    if (!ReadFile(hFile, m_sStrongName.m_pbPublicKey, m_sStrongName.m_cbPublicKey, &dwBytesRead, NULL)) {
                        hr = GetLastError();
                        report->error("Failed to read key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr);
                        m_pCurAsmRef = NULL;
                        CloseHandle(hFile);
                        return;
                    }

                    CloseHandle(hFile);

                    // Guess whether we're full or delay signing based on
                    // whether the blob passed to us looks like a public
                    // key. (I.e. we may just have copied a full key pair
                    // into the public key buffer).
                    if (m_sStrongName.m_cbPublicKey >= sizeof(PublicKeyBlob) &&
                        (offsetof(PublicKeyBlob, PublicKey) +
                         ((PublicKeyBlob*)m_sStrongName.m_pbPublicKey)->cbPublicKey) == m_sStrongName.m_cbPublicKey)
                        m_sStrongName.m_fFullSign = FALSE;
                    else
                        m_sStrongName.m_fFullSign = TRUE;

                    // If we really have a key pair, we'll move it into a
                    // key container so the signing code gets the key pair
                    // from a consistent place.
                    if (m_sStrongName.m_fFullSign)
                    {
                        m_sStrongName.m_pbPrivateKey = m_sStrongName.m_pbPublicKey;
                        m_sStrongName.m_cbPrivateKey = m_sStrongName.m_cbPublicKey;

                        m_sStrongName.m_pbPublicKey = NULL;
                        m_sStrongName.m_cbPublicKey = NULL;
                        m_sStrongName.m_dwPublicKeyAllocated = 0;

                        // Retrieve the public key portion as a byte blob.
                        if (!StrongNameGetPublicKey(NULL,
                                                    m_sStrongName.m_pbPrivateKey,
                                                    m_sStrongName.m_cbPrivateKey,
                                                    &m_sStrongName.m_pbPublicKey,
                                                    &m_sStrongName.m_cbPublicKey))
                        {
                            hr = StrongNameErrorInfo();
                            report->error("Failed to extract public key: 0x%08X\n",hr);
                            m_pCurAsmRef = NULL;
                            return;
                        }
    
                        m_sStrongName.m_dwPublicKeyAllocated = 2;
                    }
                }
            }
            else if (m_pAssembly->pPublicKey)
            {
                m_sStrongName.m_pbPublicKey = m_pAssembly->pPublicKey->ptr();
                m_sStrongName.m_cbPublicKey = m_pAssembly->pPublicKey->length();
                m_sStrongName.m_wzKeyContainer = NULL;
                m_sStrongName.m_fFullSign = FALSE;
                m_sStrongName.m_dwPublicKeyAllocated = 0;
            }
            else
            {
                m_sStrongName.m_pbPublicKey = NULL;
                m_sStrongName.m_cbPublicKey = 0;
                m_sStrongName.m_wzKeyContainer = NULL;
                m_sStrongName.m_fFullSign = FALSE;
                m_sStrongName.m_dwPublicKeyAllocated = 0;
            }

        }
        m_pCurAsmRef = NULL;
    }
    ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP();
}