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