// -------------------------------------------------------------------------------------- // // 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
// -------------------------------------------------------------------------------------- // // 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