unsigned __stdcall SectEH_Emit()

in src/InstrumentationEngine/CorHeaders.cpp [135:220]


unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount,
                  __in_ecount(ehCount) const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses,
                  bool moreSections, __inout_ecount_opt(size) BYTE* outBuff,
                  __out_ecount(ehCount) ULONG* ehTypeOffsets)
{
    HRESULT hr = S_OK;
    if (size == 0 || outBuff == nullptr)
        return 0;

    ASSERT ((((size_t) outBuff) & 3) == 0);               // header is dword aligned
    const BYTE* origBuff = outBuff;
    if (ehCount == 0 || clauses == nullptr)
        return 0;

    // Initialize the ehTypeOffsets array.
    if (ehTypeOffsets)
    {
        for (unsigned int i = 0; i < ehCount; i++)
            ehTypeOffsets[i] = (ULONG) -1;
    }

    if (COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount) < COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) {
        COR_ILMETHOD_SECT_EH_SMALL* EHSect = (COR_ILMETHOD_SECT_EH_SMALL*) outBuff;
		unsigned i;
        for (i = 0; i < ehCount; i++) {
            if (clauses[i].TryOffset > 0xFFFF ||
                    clauses[i].TryLength > 0xFF ||
                    clauses[i].HandlerOffset > 0xFFFF ||
                    clauses[i].HandlerLength > 0xFF) {
                break;  // fall through and generate as FAT
            }
            ASSERT ((clauses[i].Flags & ~0xFFFF) == 0);
            ASSERT ((clauses[i].TryOffset & ~0xFFFF) == 0);
            ASSERT ((clauses[i].TryLength & ~0xFF) == 0);
            ASSERT ((clauses[i].HandlerOffset & ~0xFFFF) == 0);
            ASSERT ((clauses[i].HandlerLength & ~0xFF) == 0);
            EHSect->Clauses[i].Flags         = (CorExceptionFlag) clauses[i].Flags;
            EHSect->Clauses[i].TryOffset     = (WORD) clauses[i].TryOffset;
            EHSect->Clauses[i].TryLength     = (WORD) clauses[i].TryLength;
            EHSect->Clauses[i].HandlerOffset = (WORD) clauses[i].HandlerOffset;
            EHSect->Clauses[i].HandlerLength = (WORD) clauses[i].HandlerLength;
            EHSect->Clauses[i].ClassToken  = clauses[i].ClassToken;
        }
        if (i >= ehCount) {
            // if actually got through all the clauses and they are small enough
            EHSect->Kind = CorILMethod_Sect_EHTable;
            if (moreSections)
                EHSect->Kind |= CorILMethod_Sect_MoreSects;
            EHSect->DataSize = EHSect->Size(ehCount);
            EHSect->Reserved = 0;
            ASSERT (EHSect->DataSize == EHSect->Size(ehCount)); // make sure didn't overflow
            outBuff = (BYTE*) &EHSect->Clauses[ehCount];
            // Set the offsets for the exception type tokens.
            if (ehTypeOffsets)
            {
                for (unsigned int j = 0; j < ehCount; j++) {
                    if (EHSect->Clauses[j].Flags == COR_ILEXCEPTION_CLAUSE_NONE)
                    {
                        ehTypeOffsets[j] = (ULONG)((BYTE *)&EHSect->Clauses[j].ClassToken - origBuff);
                    }
                }
            }
            return(size);
        }
    }
    // either total size too big or one of constituent elements too big (eg. offset or length)
    COR_ILMETHOD_SECT_EH_FAT* EHSect = (COR_ILMETHOD_SECT_EH_FAT*) outBuff;
    EHSect->Kind = CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat;
    if (moreSections)
        EHSect->Kind |= CorILMethod_Sect_MoreSects;
    EHSect->DataSize = EHSect->Size(ehCount);
    IfFailRetErrno(memcpy_s(EHSect->Clauses, ehCount * sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT), clauses, ehCount * sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)));
    outBuff = (BYTE*) &EHSect->Clauses[ehCount];
    ASSERT (&origBuff[size] == outBuff);
    // Set the offsets for the exception type tokens.
    if (ehTypeOffsets)
    {
        for (unsigned int i = 0; i < ehCount; i++) {
            if (EHSect->Clauses[i].Flags == COR_ILEXCEPTION_CLAUSE_NONE)
            {
                ehTypeOffsets[i] = (ULONG)((BYTE *)&EHSect->Clauses[i].ClassToken - origBuff);
            }
        }
    }
    return(size);
}