Beispiel #1
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
HRESULT CLiteWeightStgdb<MiniMd>::InitOnMem(
	ULONG		cbData,					// count of bytes in pData
	LPCVOID 	pData)					// points to meta data section in memory
{
	STORAGEHEADER sHdr;					// Header for the storage.
	PSTORAGESTREAM pStream;				// Pointer to each stream.
	int			bFoundMd = false;		// true when compressed data found.
	int			i;						// Loop control.
	HRESULT		hr = S_OK;

	// Don't double open.
	_ASSERTE(m_pvMd == NULL && m_cbMd == 0);

	// Validate the signature of the format, or it isn't ours.
	if (FAILED(hr = MDFormat::VerifySignature((PSTORAGESIGNATURE) pData, cbData)))
		goto ErrExit;

    m_MiniMd.m_hotTableDirectory = NULL;

	// Get back the first stream.
	pStream = MDFormat::GetFirstStream(&sHdr, pData);
    if (pStream == NULL)
        IfFailGo(CLDB_E_FILE_CORRUPT);

	// Loop through each stream and pick off the ones we need.
	for (i=0;  i<sHdr.GetiStreams();  i++)
	{        
		// Pick off the location and size of the data.
		void *pvCurrentData = (void *) ((BYTE *) pData + pStream->GetOffset());
		ULONG cbCurrentData = pStream->GetSize();


        // Get next stream 
        PSTORAGESTREAM pNext = pStream->NextStream();


        // Range check
        if ((LPBYTE) pStream >= (LPBYTE) pData + cbData ||
            (LPBYTE) pNext   >  (LPBYTE) pData + cbData )
        {
            IfFailGo( CLDB_E_FILE_CORRUPT );
        }

        if ( (LPBYTE) pvCurrentData                 >= (LPBYTE) pData + cbData ||
             (LPBYTE) pvCurrentData + cbCurrentData >  (LPBYTE) pData + cbData )
        {
            IfFailGo( CLDB_E_FILE_CORRUPT );
        }

        
        // String pool.
        if (strcmp(pStream->GetName(), STRING_POOL_STREAM_A) == 0)
        {
            METADATATRACKER_ONLY(MetaDataTracker::NoteSection(TBL_COUNT + MDPoolStrings, pvCurrentData, cbCurrentData, 1));
            IfFailGo( m_MiniMd.m_Strings.InitOnMemReadOnly(pvCurrentData, cbCurrentData) );
        }

        // Literal String Blob pool.
        else if (strcmp(pStream->GetName(), US_BLOB_POOL_STREAM_A) == 0)
        {
            METADATATRACKER_ONLY(MetaDataTracker::NoteSection(TBL_COUNT + MDPoolUSBlobs, pvCurrentData, cbCurrentData, 1));
            IfFailGo( m_MiniMd.m_USBlobs.InitOnMemReadOnly(pvCurrentData, cbCurrentData) );
        }

        // GUID pool.
        else if (strcmp(pStream->GetName(), GUID_POOL_STREAM_A) == 0)
        {
            METADATATRACKER_ONLY(MetaDataTracker::NoteSection(TBL_COUNT + MDPoolGuids, pvCurrentData, cbCurrentData, 1));
            IfFailGo( m_MiniMd.m_Guids.InitOnMemReadOnly(pvCurrentData, cbCurrentData) );
        }

        // Blob pool.
        else if (strcmp(pStream->GetName(), BLOB_POOL_STREAM_A) == 0)
        {
            METADATATRACKER_ONLY(MetaDataTracker::NoteSection(TBL_COUNT + MDPoolBlobs, pvCurrentData, cbCurrentData, 1));
            IfFailGo( m_MiniMd.m_Blobs.InitOnMemReadOnly(pvCurrentData, cbCurrentData) );
        }

        // Found the compressed meta data stream.
        else if (strcmp(pStream->GetName(), COMPRESSED_MODEL_STREAM_A) == 0)
        {
            IfFailGo( m_MiniMd.InitOnMem(pvCurrentData, cbCurrentData) );
            bFoundMd = true;
        }

        // Found the hot meta data stream
        else if (strcmp(pStream->GetName(), HOT_MODEL_STREAM_A) == 0)
        {
            BYTE * hotStreamEnd = reinterpret_cast< BYTE * >( pvCurrentData ) + cbCurrentData;
            ULONG * hotMetadataDir = reinterpret_cast< ULONG * >( hotStreamEnd ) - 2;
            ULONG hotPoolsSize = *hotMetadataDir;
            
            m_MiniMd.m_hotTableDirectory = (CMiniMd::HotTableDirectory *)
                ( reinterpret_cast< BYTE* >( hotMetadataDir ) - hotPoolsSize - sizeof(CMiniMd::HotTableDirectory) );
            m_MiniMd.m_hotTableDirectory->CheckTables();

            InitHotPools( hotMetadataDir );
        }
		// Pick off the next stream if there is one.
		pStream = pNext;
	}

	// If the meta data wasn't found, we can't handle this file.
	if (!bFoundMd)
	{
		IfFailGo( CLDB_E_FILE_CORRUPT );
	}
    else
    {   // Validate sensible heaps.
        IfFailGo( m_MiniMd.PostInit(0) );
    }

	// Save off the location.
	m_pvMd = pData;
	m_cbMd = cbData;

ErrExit:
	return (hr);
}