Ejemplo n.º 1
0
// --------------------------------------------------------------------------------------
// 
// 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
Ejemplo n.º 2
0
// --------------------------------------------------------------------------------------
// 
// Validates hot heap structure (extension of code:Initialize checks).
// 
__checkReturn 
HRESULT 
HotHeap::Debug_Validate()
{
    // Additional verification, more strict checks than in code:Initialize
    S_UINT32 nValueOffsetTableStart = 
        S_UINT32(2) * 
        S_UINT32(m_pHotHeapHeader->m_nIndexTableStart_NegativeOffset);
    if (nValueOffsetTableStart.IsOverflow() || 
        (nValueOffsetTableStart.Value() != m_pHotHeapHeader->m_nValueOffsetTableStart_NegativeOffset))
    {
        Debug_ReportError("Invalid hot heap header format.");
        return METADATA_E_INVALID_FORMAT;
    }
    if (m_pHotHeapHeader->m_nValueHeapStart_NegativeOffset <= m_pHotHeapHeader->m_nValueOffsetTableStart_NegativeOffset)
    {
        Debug_ReportError("Invalid hot heap header format.");
        return METADATA_E_INVALID_FORMAT;
    }
    
    // Already validated against underflow in code:Initialize
    BYTE   *pIndexTableStart = reinterpret_cast<BYTE *>(m_pHotHeapHeader) - m_pHotHeapHeader->m_nIndexTableStart_NegativeOffset;
    UINT32 *rgIndexTable = reinterpret_cast<UINT32 *>(pIndexTableStart);
    // Already validated against underflow in code:Initialize
    BYTE   *pValueOffsetTableStart = reinterpret_cast<BYTE *>(m_pHotHeapHeader) - m_pHotHeapHeader->m_nValueOffsetTableStart_NegativeOffset;
    UINT32 *rgValueOffsetTable = reinterpret_cast<UINT32 *>(pValueOffsetTableStart);
    // Already validated against underflow in code:Initialize
    BYTE *pValueHeapStart = reinterpret_cast<BYTE *>(m_pHotHeapHeader) - m_pHotHeapHeader->m_nValueHeapStart_NegativeOffset;
    DataBuffer valueHeap(
        pValueHeapStart, 
        m_pHotHeapHeader->m_nValueHeapStart_NegativeOffset - m_pHotHeapHeader->m_nValueOffsetTableStart_NegativeOffset);
    
    // Already validated for % 4 == 0 in code:Initialize
    UINT32 cIndexTableCount = m_pHotHeapHeader->m_nIndexTableStart_NegativeOffset / 4;
    UINT32 nPreviousValue = 0;
    for (UINT32 nIndex = 0; nIndex < cIndexTableCount; nIndex++)
    {
        if (nPreviousValue >= rgIndexTable[nIndex])
        {
            Debug_ReportError("Invalid hot heap header format.");
            return METADATA_E_INVALID_FORMAT;
        }
        UINT32 nValueOffset = rgValueOffsetTable[nIndex];
        if (nValueOffset >= valueHeap.GetSize())
        {
            Debug_ReportError("Invalid hot heap header format.");
            return METADATA_E_INVALID_FORMAT;
        }
        // TODO: Verify item (depends if it is string, blob, guid or user string)
    }
    return S_OK;
} // HotHeap::Debug_Validate
Ejemplo n.º 3
0
//*****************************************************************************
// Skip over the header and find the actual stream data.  Secure version of 
// GetFirstStream method.
// The header is supposed to be verified by VerifySignature.
// 
// Returns pointer to the first stream (behind storage header) and the size of 
// the remaining buffer in *pcbMd (could be 0).
// Returns NULL if there is not enough buffer for reading the headers. The *pcbMd 
// could be changed if NULL returned.
// 
// Caller has to check available buffer size before using the first stream.
//*****************************************************************************
PSTORAGESTREAM 
MDFormat::GetFirstStream_Verify(
    PSTORAGEHEADER pHeader,     // Return copy of header struct.
    const void    *pvMd,        // Pointer to the full file.
    ULONG         *pcbMd)       // [in, out] Size of pvMd buffer (we don't want to read behind it)
{
    const BYTE *pbMd;
    
    // Header data starts after signature.
    pbMd = (const BYTE *)pvMd;
    // Check read buffer overflow
    if (*pcbMd < sizeof(STORAGESIGNATURE))
    {
        Debug_ReportError("Invalid MetaData - Storage signature doesn't fit.");
        return NULL;
    }
    pbMd += sizeof(STORAGESIGNATURE);
    *pcbMd -= sizeof(STORAGESIGNATURE);
    
    ULONG cbVersionString = ((STORAGESIGNATURE *)pvMd)->GetVersionStringLength();
    // Check read buffer overflow
    if (*pcbMd < cbVersionString)
    {
        Debug_ReportError("Invalid MetaData storage signature - Version string doesn't fit.");
        return NULL;
    }
    pbMd += cbVersionString;
    *pcbMd -= cbVersionString;
    
    // Is there enough space for storage header?
    if (*pcbMd < sizeof(STORAGEHEADER))
    {
        Debug_ReportError("Invalid MetaData storage header - Storage header doesn't fit.");
        return NULL;
    }
    PSTORAGEHEADER pHdr = (PSTORAGEHEADER) pbMd;
    *pHeader = *pHdr;
    pbMd += sizeof(STORAGEHEADER);
    *pcbMd -= sizeof(STORAGEHEADER);
    
    // ECMA specifies that the flags field is "reserved, must be 0".
    if (pHdr->GetFlags() != 0)
    {
        Debug_ReportError("Invalid MetaData storage header - Flags are not 0.");
        return NULL;
    }
	
    // The pointer is now at the first stream in the list.
    return (PSTORAGESTREAM)pbMd;
} // MDFormat::GetFirstStream
Ejemplo n.º 4
0
// --------------------------------------------------------------------------------------
// 
// Gets stored data at index.
// Returns S_FALSE if data index is not stored in hot heap.
// 
__checkReturn 
HRESULT 
HotHeap::GetData(
         UINT32    nDataIndex, 
    __in DataBlob *pData)
{
    // Already validated against underflow in code:Initialize
    BYTE *pIndexTableStart = reinterpret_cast<BYTE *>(m_pHotHeapHeader) - m_pHotHeapHeader->m_nIndexTableStart_NegativeOffset;
    // Already validated against underflow in code:Initialize
    BYTE *pValueOffsetTableStart = reinterpret_cast<BYTE *>(m_pHotHeapHeader) - m_pHotHeapHeader->m_nValueOffsetTableStart_NegativeOffset;
    // Already validated against underflow in code:Initialize
    BYTE *pValueHeapStart = reinterpret_cast<BYTE *>(m_pHotHeapHeader) - m_pHotHeapHeader->m_nValueHeapStart_NegativeOffset;
    
    const UINT32 *pnFoundDataIndex = BinarySearch<UINT32>(
        reinterpret_cast<UINT32 *>(pIndexTableStart),
        m_pHotHeapHeader->m_nIndexTableStart_NegativeOffset / sizeof(UINT32),
        nDataIndex);

    if (pnFoundDataIndex == NULL)
    {   // Index is not stored in hot data
        return S_FALSE;
    }
    _ASSERTE(((UINT32 *)pIndexTableStart <= pnFoundDataIndex) && 
        (pnFoundDataIndex + 1 <= (UINT32 *)m_pHotHeapHeader));
    
    // Index of found data index in the index table (note: it is not offset, but really index)
    UINT32 nIndexOfFoundDataIndex = (UINT32)(pnFoundDataIndex - (UINT32 *)pIndexTableStart);
    
    // Value offset contains positive offset to the ValueHeap start
    // Already validated against overflow in code:Initialize
    UINT32 nValueOffset_PositiveOffset = reinterpret_cast<UINT32 *>(pValueOffsetTableStart)[nIndexOfFoundDataIndex];
    if (nValueOffset_PositiveOffset >= m_pHotHeapHeader->m_nValueHeapStart_NegativeOffset)
    {
        pData->Clear();
        Debug_ReportError("Invalid hot data format - value offset reaches behind the hot heap data.");
        return METADATA_E_INVALID_FORMAT;
    }
    pData->Init(
        pValueHeapStart + nValueOffset_PositiveOffset, 
        m_pHotHeapHeader->m_nValueHeapStart_NegativeOffset - nValueOffset_PositiveOffset);
    
    return S_OK;
} // HotHeap::GetData
Ejemplo n.º 5
0
// --------------------------------------------------------------------------------------
// 
// Initializes hot heap from its header and data.
// Provides limited debug-only validation of the structure.
// 
__checkReturn 
HRESULT 
HotHeap::Initialize(
    struct HotHeapHeader *pHotHeapHeader, 
    DataBuffer            hotHeapData)
{
    _ASSERTE(hotHeapData.GetDataPointerBehind() == reinterpret_cast<BYTE *>(pHotHeapHeader));
    
    UINT32 nMaximumNegativeOffset = hotHeapData.GetSize();
    if (pHotHeapHeader->m_nIndexTableStart_NegativeOffset > nMaximumNegativeOffset)
    {
        m_pHotHeapHeader = NULL;
        Debug_ReportError("Invalid hot heap header format - invalid index table offset.");
        return METADATA_E_INVALID_FORMAT;
    }
    if ((pHotHeapHeader->m_nIndexTableStart_NegativeOffset % 4) != 0)
    {
        m_pHotHeapHeader = NULL;
        Debug_ReportError("Invalid hot heap header format - index table offset is not aligned.");
        return METADATA_E_INVALID_FORMAT;
    }
    if (pHotHeapHeader->m_nValueOffsetTableStart_NegativeOffset > nMaximumNegativeOffset)
    {
        m_pHotHeapHeader = NULL;
        Debug_ReportError("Invalid hot heap header format - invalid value offset table offset.");
        return METADATA_E_INVALID_FORMAT;
    }
    if ((pHotHeapHeader->m_nValueOffsetTableStart_NegativeOffset % 4) != 0)
    {
        m_pHotHeapHeader = NULL;
        Debug_ReportError("Invalid hot heap header format - value offset table offset is not aligned.");
        return METADATA_E_INVALID_FORMAT;
    }
    // Index table has to be behind value offset table
    if (pHotHeapHeader->m_nValueOffsetTableStart_NegativeOffset < pHotHeapHeader->m_nIndexTableStart_NegativeOffset)
    {
        m_pHotHeapHeader = NULL;
        Debug_ReportError("Invalid hot heap header format - value offset table doesn't start before index table.");
        return METADATA_E_INVALID_FORMAT;
    }
    if (pHotHeapHeader->m_nValueHeapStart_NegativeOffset > nMaximumNegativeOffset)
    {
        m_pHotHeapHeader = NULL;
        Debug_ReportError("Invalid hot heap header format - invalid value heap offset.");
        return METADATA_E_INVALID_FORMAT;
    }
    m_pHotHeapHeader = pHotHeapHeader;
    return S_OK;
} // HotHeap::Initialize
Ejemplo n.º 6
0
//*****************************************************************************
// CheckFileFormat
// This function will determine if the in-memory image is a readonly, readwrite,
// or ICR format.
//*****************************************************************************
HRESULT 
CheckFileFormat(
    LPVOID        pData, 
    ULONG         cbData, 
    MDFileFormat *pFormat)  // [OUT] the file format
{
    HRESULT        hr = NOERROR;
    STORAGEHEADER  sHdr;        // Header for the storage.
    PSTORAGESTREAM pStream;     // Pointer to each stream.
    int            i;
    ULONG          cbStreamBuffer;
    
    _ASSERTE(pFormat != NULL);
    
    *pFormat = MDFormat_Invalid;
    
    // Validate the signature of the format, or it isn't ours.
    if (FAILED(hr = MDFormat::VerifySignature((PSTORAGESIGNATURE) pData, cbData)))
        goto ErrExit;
    
    // Remaining buffer size behind the stream header (pStream).
    cbStreamBuffer = cbData;
    // Get back the first stream.
    pStream = MDFormat::GetFirstStream_Verify(&sHdr, pData, &cbStreamBuffer);
    if (pStream == NULL)
    {
        Debug_ReportError("Invalid MetaData storage signature - cannot get the first stream header.");
        IfFailGo(CLDB_E_FILE_CORRUPT);
    }
    
    // Loop through each stream and pick off the ones we need.
    for (i = 0; i < sHdr.GetiStreams(); i++)
    {
        // Do we have enough buffer to read stream header?
        if (cbStreamBuffer < sizeof(*pStream))
        {
            Debug_ReportError("Stream header is not within MetaData block.");
            IfFailGo(CLDB_E_FILE_CORRUPT);
        }
        // Get next stream.
        PSTORAGESTREAM pNext = pStream->NextStream_Verify();
        
        // Check that stream header is within the buffer.
        if (((LPBYTE)pStream >= ((LPBYTE)pData + cbData)) ||
            ((LPBYTE)pNext   >  ((LPBYTE)pData + cbData)))
        {
            Debug_ReportError("Stream header is not within MetaData block.");
            hr = CLDB_E_FILE_CORRUPT;
            goto ErrExit;
        }
        
        // Check that the stream data starts and fits within the buffer.
        //  need two checks on size because of wraparound.
        if ((pStream->GetOffset() > cbData) || 
            (pStream->GetSize() > cbData) || 
            ((pStream->GetSize() + pStream->GetOffset()) < pStream->GetOffset()) || 
            ((pStream->GetSize() + pStream->GetOffset()) > cbData))
        {
            Debug_ReportError("Stream data are not within MetaData block.");
            hr = CLDB_E_FILE_CORRUPT;
            goto ErrExit;
        }
        
        // Pick off the location and size of the data.
        
        if (strcmp(pStream->GetName(), COMPRESSED_MODEL_STREAM_A) == 0)
        {
            // Validate that only one of compressed/uncompressed is present.
            if (*pFormat != MDFormat_Invalid)
            {   // Already found a good stream.
                Debug_ReportError("Compressed model stream #~ is second important stream.");
                hr = CLDB_E_FILE_CORRUPT;
                goto ErrExit;
            }
            // Found the compressed meta data stream.
            *pFormat = MDFormat_ReadOnly;
        }
        else if (strcmp(pStream->GetName(), ENC_MODEL_STREAM_A) == 0)
        {
            // Validate that only one of compressed/uncompressed is present.
            if (*pFormat != MDFormat_Invalid)
            {   // Already found a good stream.
                Debug_ReportError("ENC model stream #- is second important stream.");
                hr = CLDB_E_FILE_CORRUPT;
                goto ErrExit;
            }
            // Found the ENC meta data stream.
            *pFormat = MDFormat_ReadWrite;
        }
        else if (strcmp(pStream->GetName(), SCHEMA_STREAM_A) == 0)
        {
            // Found the uncompressed format
            *pFormat = MDFormat_ICR;
            
            // keep going. We may find the compressed format later. 
            // If so, we want to use the compressed format.
        }
        
        // Pick off the next stream if there is one.
        pStream = pNext;
        cbStreamBuffer = (ULONG)((LPBYTE)pData + cbData - (LPBYTE)pNext);
    }
    
    if (*pFormat == MDFormat_Invalid)
    {   // Didn't find a good stream.
        Debug_ReportError("Cannot find MetaData stream.");
        hr = CLDB_E_FILE_CORRUPT;
    }
    
ErrExit:
    return hr;
} // CheckFileFormat
Ejemplo n.º 7
0
//*****************************************************************************
// Given an StgIO, opens compressed streams and do proper initialization.
// This is a helper for other Init functions.
//*****************************************************************************
__checkReturn 
HRESULT 
CLiteWeightStgdbRW::InitFileForRead(
    StgIO * pStgIO,     // For file i/o.
    int     bReadOnly)  // If read-only open.
{
    TiggerStorage * pStorage = NULL;
    void          * pvData;
    ULONG           cbData;
    HRESULT         hr = NOERROR;
    
    // Allocate a new storage object which has IStorage on it.
    pStorage = new (nothrow) TiggerStorage();
    IfNullGo(pStorage);
    
    // Init the storage object on the backing storage.
    OptionValue ov;
    IfFailGo(m_MiniMd.GetOption(&ov));
    IfFailGo(pStorage->Init(pStgIO, ov.m_RuntimeVersion));
    
    // Save pointers to header structure for version string.
    _ASSERTE((m_pvMd == NULL) && (m_cbMd == 0));
    IfFailGo(pStorage->GetHeaderPointer(&m_pvMd, &m_cbMd));
    
    // Check to see if this is a minimal metadata
    if (SUCCEEDED(pStorage->OpenStream(MINIMAL_MD_STREAM, &cbData, &pvData)))
    {
        m_MiniMd.m_fMinimalDelta = TRUE;
    }
    
    // Load the string pool.
    if (SUCCEEDED(hr = pStorage->OpenStream(STRING_POOL_STREAM, &cbData, &pvData)))
    {
        // String pool has to end with a null-terminator, therefore we don't have to check string pool 
        // content on access.
        // Shrink size of the pool to the last null-terminator found.
        while (cbData != 0)
        {
            if (((LPBYTE)pvData)[cbData - 1] == 0)
            {   // We have found last null terminator
                break;
            }
            // Shrink size of the pool
            cbData--;
            Debug_ReportError("String heap/pool does not end with null-terminator ... shrinking the heap.");
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolStrings, pvData, cbData, bReadOnly));
    }
    else
    {
        if (hr != STG_E_FILENOTFOUND)
        {
            IfFailGo(hr);
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolStrings, NULL, 0, bReadOnly));
    }
    
    // Load the user string blob pool.
    if (SUCCEEDED(hr = pStorage->OpenStream(US_BLOB_POOL_STREAM, &cbData, &pvData)))
    {
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolUSBlobs, pvData, cbData, bReadOnly));
    }
    else
    {
        if (hr != STG_E_FILENOTFOUND)
        {
            IfFailGo(hr);
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolUSBlobs, NULL, 0, bReadOnly));
    }
    
    // Load the guid pool.
    if (SUCCEEDED(hr = pStorage->OpenStream(GUID_POOL_STREAM, &cbData, &pvData)))
    {
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolGuids, pvData, cbData, bReadOnly));
    }
    else
    {
        if (hr != STG_E_FILENOTFOUND)
        {
            IfFailGo(hr);
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolGuids, NULL, 0, bReadOnly));
    }
    
    // Load the blob pool.
    if (SUCCEEDED(hr = pStorage->OpenStream(BLOB_POOL_STREAM, &cbData, &pvData)))
    {
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolBlobs, pvData, cbData, bReadOnly));
    }
    else
    {
        if (hr != STG_E_FILENOTFOUND)
        {
            IfFailGo(hr);
        }
        IfFailGo(m_MiniMd.InitPoolOnMem(MDPoolBlobs, NULL, 0, bReadOnly));
    }
    
    // Open the metadata.
    hr = pStorage->OpenStream(COMPRESSED_MODEL_STREAM, &cbData, &pvData);
    if (hr == STG_E_FILENOTFOUND)
    {
        IfFailGo(pStorage->OpenStream(ENC_MODEL_STREAM, &cbData, &pvData));
    }
    IfFailGo(m_MiniMd.InitOnMem(pvData, cbData, bReadOnly));
    IfFailGo(m_MiniMd.PostInit(0));
    
ErrExit:
    if (pStorage != NULL)
    {
        delete pStorage;
    }
    return hr;
} // CLiteWeightStgdbRW::InitFileForRead
Ejemplo n.º 8
0
//*****************************************************************************
// Get info about the MD stream.
// Low level access to stream data.  Intended for metainfo, and such.
//*****************************************************************************
__checkReturn 
STDMETHODIMP 
CLiteWeightStgdbRW::GetRawStreamInfo(
    ULONG        ix,            // [IN] Stream ordinal desired.
    const char **ppchName,      // [OUT] put pointer to stream name here.
    const void **ppv,           // [OUT] put pointer to MD stream here.
    ULONG       *pcb)           // [OUT] put size of the stream here.
{
    HRESULT        hr = NOERROR;
    STORAGEHEADER  sHdr;            // Header for the storage.
    PSTORAGESTREAM pStream;         // Pointer to each stream.
    ULONG          i;               // Loop control.
    void          *pData;
    ULONG          cbData;

#ifdef FEATURE_METADATA_CUSTOM_DATA_SOURCE
    if (m_pStgIO == NULL)
        IfFailGo(COR_E_NOTSUPPORTED);
#endif

    pData = m_pStgIO->m_pData;
    cbData = m_pStgIO->m_cbData;
    
    // Validate the signature of the format, or it isn't ours.
    IfFailGo(MDFormat::VerifySignature((PSTORAGESIGNATURE) pData, cbData));
    
    // Get back the first stream.
    pStream = MDFormat::GetFirstStream(&sHdr, pData);
    if (pStream == NULL)
    {
        Debug_ReportError("Invalid MetaData storage signature - cannot get the first stream header.");
        IfFailGo(CLDB_E_FILE_CORRUPT);
    }
    
    // Check that the requested stream exists.
    if (ix >= sHdr.GetiStreams())
        return S_FALSE;
    
    // Skip to the desired stream.
    for (i = 0; i < ix; i++)
    {
        PSTORAGESTREAM pNext = pStream->NextStream();
        
        // Check that stream header is within the buffer.
        if (((LPBYTE)pStream >= ((LPBYTE)pData + cbData)) || 
            ((LPBYTE)pNext   >  ((LPBYTE)pData + cbData)))
        {
            Debug_ReportError("Stream header is not within MetaData block.");
            hr = CLDB_E_FILE_CORRUPT;
            goto ErrExit;
        }
        
        // Check that the stream data starts and fits within the buffer.
        //  need two checks on size because of wraparound.
        if ((pStream->GetOffset() > cbData) || 
            (pStream->GetSize() > cbData) || 
            ((pStream->GetSize() + pStream->GetOffset()) > cbData))
        {
            Debug_ReportError("Stream data are not within MetaData block.");
            hr = CLDB_E_FILE_CORRUPT;
            goto ErrExit;
        }
        
        // Pick off the next stream if there is one.
        pStream = pNext;
    }
    
    if (pStream != NULL)
    {
        *ppv = (const void *)((const BYTE *)pData + pStream->GetOffset());
        *pcb = pStream->GetSize();
        *ppchName = pStream->GetName();
    }
    else
    {
        *ppv = NULL;
        *pcb = 0;
        *ppchName = NULL;
        
        // Invalid input to the method
        hr = CLDB_E_FILE_CORRUPT;
    }
    
ErrExit:
    return hr;
} // CLiteWeightStgdbRW::GetRawStreamInfo
Ejemplo n.º 9
0
HRESULT 
MDFormat::VerifySignature(
    PSTORAGESIGNATURE pSig,     // The signature to check.
    ULONG             cbData)
{
    HRESULT hr = S_OK;
    
    // If signature didn't match, you shouldn't be here.
    ULONG dwSignature = pSig->GetSignature();
    if (dwSignature == STORAGE_MAGIC_OLD_SIG)
    {
        Debug_ReportError("Invalid MetaData storage signature - old magic signature +MOC.");
        return PostError(CLDB_E_FILE_OLDVER, 1, 0);
    }
    if (dwSignature != STORAGE_MAGIC_SIG)
    {
        Debug_ReportError("Invalid MetaData storage signature - unrecognized magic signature, should be BSJB.");
        return PostError(CLDB_E_FILE_CORRUPT);
    }
    
    // Check for overflow
    ULONG lVersionString = pSig->GetVersionStringLength();
    ULONG sum = sizeof(STORAGESIGNATURE) + lVersionString;
    if ((sum < sizeof(STORAGESIGNATURE)) || (sum < lVersionString))
    {
        Debug_ReportError("Invalid MetaData storage signature - version string too long, integer overflow.");
        return PostError(CLDB_E_FILE_CORRUPT);
    }
    
    // Check for invalid version string size
    if ((sizeof(STORAGESIGNATURE) + lVersionString) > cbData)
    {
        Debug_ReportError("Invalid MetaData storage signature - version string too long.");
        return PostError(CLDB_E_FILE_CORRUPT);
    }
    
    // Check that the version string is null terminated. This string
    // is ANSI, so no double-null checks need to be made.
    {
        BYTE *pStart = &pSig->pVersion[0];
        BYTE *pEnd = pStart + lVersionString + 1; // Account for terminating NULL
        BYTE *pCur;
        
        for (pCur = pStart; pCur < pEnd; pCur++)
        {
            if (*pCur == 0)
                break;
        }
        
        // If we got to the end without hitting a NULL, we have a bad version string
        if (pCur == pEnd)
        {
            Debug_ReportError("Invalid MetaData storage signature - version string has not null-terminator.");
            return PostError(CLDB_E_FILE_CORRUPT);
        }
    }
    
#if !defined(FEATURE_METADATA_STANDALONE_WINRT)
    // Only a specific version of the 0.x format is supported by this code
    // in order to support the NT 5 beta clients which used this format.
    if (pSig->GetMajorVer() == FILE_VER_MAJOR_v0)
    {
        if (pSig->GetMinorVer() < FILE_VER_MINOR_v0)
        {
            Debug_ReportError("Invalid MetaData storage signature - unrecognized version, should be 1.1.");
            hr = CLDB_E_FILE_OLDVER;
        }
    }
    else
#endif  // !defined(FEATURE_METADATA_STANDALONE_WINRT)
    // There is currently no code to migrate an old format of the 1.x.  This
    // would be added only under special circumstances.
    if ((pSig->GetMajorVer() != FILE_VER_MAJOR) || (pSig->GetMinorVer() != FILE_VER_MINOR))
    {
        Debug_ReportError("Invalid MetaData storage signature - unrecognized version, should be 1.1.");
        hr = CLDB_E_FILE_OLDVER;
    }

    if (FAILED(hr))
        hr = PostError(hr, (int)pSig->GetMajorVer(), (int)pSig->GetMinorVer());
    return hr;
} // MDFormat::VerifySignature