예제 #1
0
파일: asmlink.cpp 프로젝트: ArildF/masters
HRESULT CAsmLink::GetResolutionScope(mdAssembly AssemblyID, mdToken FileToken, mdToken TargetFile, mdToken* pScope)
{
    ASSERT(m_bInited && !m_bPreClosed && m_pAssem);
    ASSERT(AssemblyID == TokenFromRid(mdtAssembly, 1) || AssemblyID == AssemblyIsUBM);
    ASSERT((RidFromToken(FileToken) < m_pAssem->CountFiles() && TypeFromToken(FileToken) == mdtFile) ||
        (FileToken == AssemblyID));
    ASSERT(pScope != NULL);

    if (FileToken == TargetFile) {
        *pScope = TokenFromRid(1, mdtModule);
        return S_OK;
    }

    HRESULT hr = S_OK;
    CFile *file = NULL;
    if (FileToken == AssemblyID) {
        file = m_pAssem;
    } else {
        if (FAILED(hr = m_pAssem->GetFile(FileToken, &file)))
            return hr;
    }

    if (TypeFromToken(TargetFile) == mdtFile) {
        // make a moduleref to target file in "file"
        CFile *target;
        if (FAILED(hr = m_pAssem->GetFile(TargetFile, &target)))
            return hr;
        hr = target->MakeModuleRef(file->GetEmitScope(), pScope);
    } else if (TypeFromToken(TargetFile) == mdtModule) {
        // make a moduleref to target file in "file"
        CFile *target;
        if (FAILED(hr = m_pModules->GetFile(TargetFile, &target)))
            return hr;
        hr = target->MakeModuleRef(file->GetEmitScope(), pScope);
    } else if (TypeFromToken(TargetFile) == mdtAssembly) {
        ASSERT(TargetFile != AssemblyIsUBM);
        // make a moduleref to the manifest file in "file"
        hr = m_pAssem->MakeModuleRef(file->GetEmitScope(), pScope);
    } else if (TypeFromToken(TargetFile) == mdtAssemblyRef) {
        // make an assembly ref in "file"
        CFile *target;
        if (FAILED(hr = m_pImports->GetFile(TargetFile, &target)))
            return hr;
        if (file == m_pAssem)
            // Special Case this so we don't have to re-QI for the AssemblyEmit interface
            hr = ((CAssemblyFile*)target)->MakeAssemblyRef(m_pAssem->GetEmitter(), pScope);
        else
            hr = ((CAssemblyFile*)target)->MakeAssemblyRef(file->GetEmitScope(), pScope);
    } else
        hr = E_INVALIDARG;

    return hr;
}
예제 #2
0
파일: asmlink.cpp 프로젝트: ArildF/masters
HRESULT CAsmLink::SetAssemblyProps(mdAssembly AssemblyID, mdToken FileToken, AssemblyOptions Option, VARIANT Value)
{
    ASSERT(m_bInited && !m_bPreClosed && m_pAssem && !m_bManifestEmitted);
    ASSERT(AssemblyID == TokenFromRid(mdtAssembly, 1) || AssemblyID == AssemblyIsUBM);
    ASSERT((RidFromToken(FileToken) < m_pAssem->CountFiles() && TypeFromToken(FileToken) == mdtFile) ||
        (FileToken == AssemblyID));

    HRESULT hr = S_OK;
    if (Option >= optLastAssemOption || OptionCAs[Option].flag & 0x40)
        return E_INVALIDARG;
    if (AssemblyID == AssemblyIsUBM || (OptionCAs[Option].flag & 0x02)) {
        CFile *file = NULL;
        if (FileToken == AssemblyID)
            file = m_pAssem;
        else if (FAILED(hr = m_pAssem->GetFile(FileToken, &file)))
            return hr;

        ASSERT(file->GetEmitScope());
        IMetaDataEmit* pEmit = file->GetEmitScope();
        CComPtr<IMetaDataImport> pImport;
        mdToken tkAttrib = mdTokenNil, tkCtor;
        DWORD cbValue = 0, cbSig = 4;
        BYTE pbValue[2048];
        PBYTE pBlob = pbValue;
        COR_SIGNATURE newSig[9];
        LPCWSTR wszStr = NULL;
        ULONG wLen = 0;

        if (FAILED(hr = pEmit->QueryInterface(IID_IMetaDataImport, (void**)&pImport)))
            return hr;

        // Find or Create the TypeRef (This always scopes it to MSCORLIB)
        if (FAILED(hr = file->GetTypeRef(OptionCAs[Option].name, &tkAttrib)))
            return hr;

        // Make the Blob
        newSig[0] = (IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS);
        newSig[1] = 1; // One parameter
        newSig[2] = ELEMENT_TYPE_VOID;
        *(WORD*)pBlob = VAL16(1); // This is aligned
        pBlob += sizeof(WORD);

        if (V_VT(&Value) != OptionCAs[Option].vt)
            return E_INVALIDARG;
        switch(OptionCAs[Option].vt) {
        case VT_BOOL:
            *pBlob++ = (V_BOOL(&Value) == VARIANT_TRUE);
            newSig[3] = ELEMENT_TYPE_BOOLEAN;
            break;
        case VT_UI4:
            SET_UNALIGNED_VAL32(pBlob, V_UI4(&Value));
            pBlob += sizeof(ULONG);
            newSig[3] = ELEMENT_TYPE_U4;
            break;
        case VT_BSTR:
            if (Option == optAssemOS) {
                LPWSTR end = NULL;
                mdToken tkPlatform = mdTokenNil;
                newSig[1] = 2; // Two parameters
                newSig[3] = ELEMENT_TYPE_VALUETYPE;

                // Make the TypeRef
                if (FAILED(hr = file->GetTypeRef( PLATFORMID_NAME, &tkPlatform)))
                     break;

                cbSig = 5 + CorSigCompressToken(tkPlatform, newSig + 4);
                newSig[cbSig - 1] = ELEMENT_TYPE_STRING;
                SET_UNALIGNED_VAL32(pBlob, wcstoul(V_BSTR(&Value), &end, 0)); // Parse Hex, Octal, and Decimal
                pBlob += sizeof(ULONG);
                if (*end == L'.') {
                    wszStr = end++;
                    wLen = SysStringLen(V_BSTR(&Value)) - (UINT)(V_BSTR(&Value) - end);
                    goto ADDSTRING;
                } else {
                    hr = file->ReportError(ERR_InvalidOSString);
                    return hr;
                }
            } else {
                newSig[3] = ELEMENT_TYPE_STRING;
                wLen = SysStringLen(V_BSTR(&Value));
                wszStr = V_BSTR(&Value);
ADDSTRING:
                if (wLen == 0) {
                    // Too small for unilib
                    *pBlob++ = 0xFF;
                } else if (wLen & 0x80000000) {
                    // Too big!
                    return ReportOptionError(file, Option, E_INVALIDARG);
                } else if ((OptionCAs[Option].flag & 0x10) && wLen > MAX_PATH) {
                    // Too big!
                    return ReportOptionError(file, Option, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW)); // File name too long
                } else {
                    CHAR pUTF8[2048];
                    int iLen = wLen;
    
                    wLen = (UINT)UnicodeToUTF8(wszStr, &iLen, pUTF8, lengthof(pUTF8));

                    iLen = (int)CorSigCompressData( wLen, pBlob);
                    pBlob += iLen;
                    if (wLen > (UINT)(pbValue + lengthof(pbValue) - pBlob)) {
                        // Too big!
                        return ReportOptionError(file, Option, HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
                    }
                    memcpy(pBlob, pUTF8, wLen);
                    pBlob += wLen;
                }
            }
            break;
        default:
            VSFAIL("Unknown Option Type!");
            newSig[3] = ELEMENT_TYPE_OBJECT;
            break;
        }
        hr = pImport->FindMemberRef(tkAttrib, L".ctor", newSig, cbSig, &tkCtor);
        if ((hr == CLDB_E_RECORD_NOTFOUND && FAILED(hr = pEmit->DefineMemberRef(tkAttrib, L".ctor", newSig, 4, &tkCtor))) ||
            FAILED(hr))
            return hr;
        cbValue = (DWORD)(pBlob - pbValue);

        // Emit the CA
        // This will also set the option if appropriate
        hr = EmitAssemblyCustomAttribute( AssemblyID, FileToken, tkCtor, pbValue, cbValue, 
            (OptionCAs[Option].flag & 0x08) ? TRUE : FALSE,
            (OptionCAs[Option].flag & 0x04) ? TRUE : FALSE);
    } else {
        // An assembly level custom attribute
        hr = m_pAssem->SetOption(Option, &Value);
    }
    return hr;
}