//***************************************************************************** // Add a stream, and its size, to the list of streams to be saved. //***************************************************************************** HRESULT CLiteWeightStgdbRW::AddStreamToList( ULONG cbSize, LPCWSTR szName) { HRESULT hr = S_OK; PSTORAGESTREAM pItem; // New item to allocate & fill. // Add a new item to the end of the list. IfNullGo(pItem = m_pStreamList->Append()); // Fill out the data. pItem->SetOffset(0); pItem->SetSize(cbSize); pItem->SetName(szName); ErrExit: return hr; }
//***************************************************************************** // 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
//***************************************************************************** // 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); }