// --------------------------------------------------------------------------------------
// 
// Gets next hot heap (*pHotHeap, of index *pHotHeapIndex) from the heaps directory.
// Returns S_OK and fills *pHotHeap and *pHotHeapIndex with the next code:HotHeap information.
// Returns S_FALSE, if the last hot heap was already returned. Clears *pHotHeap and *pHotHeapIndex in this 
// case.
// Returns error code if the format is invalid. Clears *pHotHeap and *pHotHeapIndex in this case.
// 
__checkReturn 
HRESULT 
HotHeapsDirectoryIterator::GetNext(
    HotHeap   *pHotHeap, 
    HeapIndex *pHotHeapIndex)
{
    HRESULT hr;
    DataBuffer hotHeapHeaderData;
    DataBuffer hotHeapData;
    
    struct HotHeapsDirectoryEntry *pEntry;
    if (!m_RemainingHeapsDirectoryData.GetData<struct HotHeapsDirectoryEntry>(
        &pEntry))
    {
        hr = S_FALSE;
        goto ErrExit;
    }
    
    if (!HeapIndex::IsValid(pEntry->m_nHeapIndex))
    {
        Debug_ReportError("Invalid hot heaps directory format - invalid heap index.");
        IfFailGo(METADATA_E_INVALID_FORMAT);
    }
    pHotHeapIndex->Set(pEntry->m_nHeapIndex);
    
    hotHeapHeaderData = m_HotHeapsData;
    if (!hotHeapHeaderData.SkipToExactSize(pEntry->m_nHeapHeaderStart_NegativeOffset))
    {
        Debug_ReportError("Invalid hot heaps directory format - heap header offset reaches in front of of hot heaps data.");
        IfFailGo(METADATA_E_INVALID_FORMAT);
    }
    
    struct HotHeapHeader *pHeader;
    if (!hotHeapHeaderData.PeekData<struct HotHeapHeader>(&pHeader))
    {
        Debug_ReportError("Invalid hot heaps directory format - heap header reaches behind hot heaps data.");
        IfFailGo(METADATA_E_INVALID_FORMAT);
    }
    
    hotHeapData = m_HotHeapsData;
    if (!hotHeapData.TruncateBySize(pEntry->m_nHeapHeaderStart_NegativeOffset))
    {
        Debug_ReportInternalError("There's a bug because previous call to SkipToExactSize succeeded.");
        IfFailGo(METADATA_E_INVALID_FORMAT);
    }
    
    IfFailGo(pHotHeap->Initialize(pHeader, hotHeapData));
    _ASSERTE(hr == S_OK);
    return hr;
ErrExit:
    pHotHeap->Clear();
    pHotHeapIndex->SetInvalid();
    return hr;
} // HotHeapsDirectoryIterator::GetNext
Exemplo n.º 2
0
// --------------------------------------------------------------------------------------
// 
// Returns heap data at index (nIndex).
// 
__checkReturn 
HRESULT 
HotHeapWriter::GetData(
    UINT32    nIndex, 
    DataBlob *pData) const
{
    HRESULT hr;
    
    switch (m_HeapIndex.Get())
    {
    case HeapIndex::StringHeapIndex:
        {
            LPCSTR szString;
            IfFailGo(m_pStringHeap->GetString(
                nIndex, 
                &szString));
            _ASSERTE(hr == S_OK);
            
            // This should not overflow, because we checked it before, but it doesn't hurt
            S_UINT32 cbStringSize = S_UINT32(strlen(szString)) + S_UINT32(1);
            if (cbStringSize.IsOverflow())
            {
                Debug_ReportInternalError("There's a bug in the string heap consistency - string is too long.");
                IfFailGo(METADATA_E_INTERNAL_ERROR);
            }
            
            pData->Init((BYTE *)szString, cbStringSize.Value());
            return S_OK;
        }
    case HeapIndex::GuidHeapIndex:
        {
            // The nIndex is in fact 0-based offset into GUID heap (0, 16, 32, ...), convert it to 1-based element index (1, 2, 3, ...) for GetGuid method
            if ((nIndex % sizeof(GUID)) != 0)
            {
                Debug_ReportInternalError("There's a bug in the caller/IBC - this should be GUID offset aligned to 16-B.");
                IfFailGo(METADATA_E_INTERNAL_ERROR);
            }
            nIndex = (nIndex / sizeof(GUID)) + 1;
            
            GUID UNALIGNED *pGuid;
            IfFailGo(const_cast<GuidHeapRW *>(m_pGuidHeap)->GetGuid(
                nIndex, 
                &pGuid));
            _ASSERTE(hr == S_OK);
            pData->Init((BYTE *)pGuid, sizeof(GUID));
            return S_OK;
        }
    case HeapIndex::BlobHeapIndex:
    case HeapIndex::UserStringHeapIndex:
        {
            IfFailGo(const_cast<BlobHeapRW *>(m_pBlobHeap)->GetBlobWithSizePrefix(
                nIndex, 
                pData));
            _ASSERTE(hr == S_OK);
            
            return S_OK;
        }
    default:
        Debug_ReportInternalError("There's a bug in the caller - this is wrong heap index.");
        IfFailGo(METADATA_E_INTERNAL_ERROR);
    }
    return S_OK;
    
ErrExit:
    pData->Clear();
    return hr;
} // HotHeapWriter::GetData