Пример #1
0
// copied from asmparse.y
static void corEmitInt(BinStr* buff, unsigned data) 
{
    unsigned cnt = CorSigCompressData(data, buff->getBuff(5));
    buff->remove(5 - cnt);
}
Пример #2
0
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;
}
Пример #3
0
//*****************************************************************************
// copy fixed part of VarArg signature to a buffer
//*****************************************************************************
HRESULT _GetFixedSigOfVarArg(           // S_OK or error.
    PCCOR_SIGNATURE pvSigBlob,          // [IN] point to a blob of COM+ method signature
    ULONG   cbSigBlob,                  // [IN] size of signature
    CQuickBytes *pqbSig,                // [OUT] output buffer for fixed part of VarArg Signature
    ULONG   *pcbSigBlob)                // [OUT] number of bytes written to the above output buffer
{
    HRESULT     hr = NOERROR;
    ULONG       cbCalling;
    ULONG       cbTyArgsNumber = 0;     // number of bytes to store the type arg count (generics only)
    ULONG       cbArgsNumber;           // number of bytes to store the original arg count
    ULONG       cbArgsNumberTemp;       // number of bytes to store the fixed arg count
    ULONG       cbTotal = 0;            // total of number bytes for return type + all fixed arguments
    ULONG       cbCur = 0;              // index through the pvSigBlob
    ULONG       cb;
    ULONG       cArg;
    ULONG       cTyArg;
    ULONG       callingconv;
    ULONG       cArgsIndex;
    CorElementType ulElementType;
    BYTE        *pbSig;

    _ASSERTE (pvSigBlob && pcbSigBlob);

    // remember the number of bytes to represent the calling convention
    cbCalling = CorSigUncompressData (pvSigBlob, &callingconv);
    if (cbCalling == ((ULONG)(-1)))
    {
        return E_INVALIDARG;
    }
    _ASSERTE (isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_VARARG));
    cbCur += cbCalling;

    if (callingconv & IMAGE_CEE_CS_CALLCONV_GENERIC)
    {
        cbTyArgsNumber = CorSigUncompressData(&pvSigBlob[cbCur], &cTyArg);
        if (cbTyArgsNumber == ((ULONG)(-1)))
        {
            return E_INVALIDARG;
        }
        cbCur += cbTyArgsNumber;
    }

    // remember number of bytes to represent the arg counts
    cbArgsNumber= CorSigUncompressData (&pvSigBlob[cbCur], &cArg);
    if (cbArgsNumber == ((ULONG)(-1)))
    {
        return E_INVALIDARG;
    }
    
    cbCur += cbArgsNumber;

    // how many bytes to represent the return type
    cb = cbSigBlob-cbCur;
    IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) );
    cbCur += cb;
    cbTotal += cb;

    // loop through argument until we found ELEMENT_TYPE_SENTINEL or run
    // out of arguments
    for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++)
    {
        _ASSERTE(cbCur < cbSigBlob);

        // peak the outer most ELEMENT_TYPE_*
        CorSigUncompressElementType (&pvSigBlob[cbCur], &ulElementType);
        if (ulElementType == ELEMENT_TYPE_SENTINEL)
            break;
        cb = cbSigBlob-cbCur;
        IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) );
        cbTotal += cb;
        cbCur += cb;
    }

    cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &cArg);

    // now cbCalling : the number of bytes needed to store the calling convention
    // cbArgNumberTemp : number of bytes to store the fixed arg count
    // cbTotal : the number of bytes to store the ret and fixed arguments

    *pcbSigBlob = cbCalling + cbArgsNumberTemp + cbTotal;

    // resize the buffer
    IfFailGo( pqbSig->ReSizeNoThrow(*pcbSigBlob) );
    pbSig = (BYTE *)pqbSig->Ptr();

    // copy over the calling convention
    cb = CorSigCompressData(callingconv, pbSig);

    // copy over the fixed arg count
    cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &pbSig[cb]);

    // copy over the fixed args + ret type
    memcpy(&pbSig[cb + cbArgsNumberTemp], &pvSigBlob[cbCalling + cbArgsNumber], cbTotal);

ErrExit:
    return hr;
}