1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //*****************************************************************************
9 // Read only pools are used to reduce the amount of data actually required in the database.
11 //*****************************************************************************
12 #include "stdafx.h" // Standard include.
13 #include <stgpool.h> // Our interface definitions.
14 #include "metadatatracker.h"
21 #if METADATATRACKER_ENABLED
22 MetaDataTracker *MetaDataTracker::m_MDTrackers = NULL;
23 BOOL MetaDataTracker::s_bEnabled = FALSE;
25 void (*MetaDataTracker::s_IBCLogMetaDataAccess)(const void *addr) = NULL;
26 void (*MetaDataTracker::s_IBCLogMetaDataSearch)(const void *result) = NULL;
28 #endif // METADATATRACKER_ENABLED
30 const BYTE StgPoolSeg::m_zeros[64] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
31 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
32 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
33 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
36 //*****************************************************************************
37 // Free any memory we allocated.
38 //*****************************************************************************
39 StgPoolReadOnly::~StgPoolReadOnly()
41 LIMITED_METHOD_CONTRACT;
45 //*****************************************************************************
46 // Init the pool from existing data.
47 //*****************************************************************************
48 HRESULT StgPoolReadOnly::InitOnMemReadOnly(// Return code.
49 void *pData, // Predefined data.
50 ULONG iSize) // Size of data.
55 INJECT_FAULT(return E_OUTOFMEMORY);
59 // Make sure we aren't stomping anything and are properly initialized.
60 _ASSERTE(m_pSegData == m_zeros);
62 // Create case requires no further action.
66 // Keep m_zeros data pointer if there's no content of the pool
69 m_pSegData = reinterpret_cast<BYTE*>(pData);
76 //*****************************************************************************
77 // Prepare to shut down or reinitialize.
78 //*****************************************************************************
79 void StgPoolReadOnly::Uninit()
81 LIMITED_METHOD_CONTRACT;
83 m_pSegData = (BYTE*)m_zeros;
88 //*****************************************************************************
89 // Convert a string to UNICODE into the caller's buffer.
90 //*****************************************************************************
91 HRESULT StgPoolReadOnly::GetStringW( // Return code.
92 ULONG iOffset, // Offset of string in pool.
93 __out_ecount(cchBuffer) LPWSTR szOut, // Output buffer for string.
94 int cchBuffer) // Size of output buffer.
96 STATIC_CONTRACT_NOTHROW;
97 STATIC_CONTRACT_FAULT;
100 LPCSTR pString; // The string in UTF8.
103 IfFailRet(GetString(iOffset, &pString));
104 iChars = ::WszMultiByteToWideChar(CP_UTF8, 0, pString, -1, szOut, cchBuffer);
106 return (BadError(HRESULT_FROM_NT(GetLastError())));
110 //*****************************************************************************
111 // Return a pointer to a null terminated blob given an offset previously
112 // handed out by Addblob or Findblob.
113 //*****************************************************************************
115 StgPoolReadOnly::GetBlob(
116 UINT32 nOffset, // Offset of blob in pool.
117 MetaData::DataBlob *pData)
119 STATIC_CONTRACT_NOTHROW;
120 STATIC_CONTRACT_FORBID_FAULT;
123 UINT32 cbBlobContentSize;
125 // This should not be a necessary special case. The zero byte at the
126 // start of the pool will code for a length of zero. We will return
127 // a pointer to the next length byte, but the caller should notice that
128 // the size is zero, and should not look at any bytes.
129 // [SL] Yes, but we don't need all further computations and checks if iOffset==0
137 // Is the offset within this heap?
138 if (!IsValidOffset(nOffset))
140 Debug_ReportError("Invalid blob offset.");
141 IfFailGo(CLDB_E_INDEX_NOTFOUND);
144 IfFailGo(GetDataReadOnly(nOffset, pData));
145 if (!pData->GetCompressedU(&cbBlobContentSize))
147 Debug_ReportError("Invalid blob - size compression.");
148 IfFailGo(COR_E_BADIMAGEFORMAT);
150 if (!pData->TruncateToExactSize(cbBlobContentSize))
152 Debug_ReportError("Invalid blob - reaches behind the end of data block.");
153 IfFailGo(COR_E_BADIMAGEFORMAT);
160 } // StgPoolReadOnly::GetBlob
162 //*****************************************************************************
163 // code:StgPoolReadOnly::GetBlob specialization with inlined check for valid offsets to avoid redundant code:StgPoolReadOnly::GetDataReadOnly calls.
164 // code:StgPoolReadOnly::GetDataReadOnly is not cheap because of it performs binary lookup in hot metadata.
165 //*****************************************************************************
167 StgBlobPoolReadOnly::GetBlob(
168 UINT32 nOffset, // Offset of blob in pool.
169 MetaData::DataBlob *pData)
171 STATIC_CONTRACT_NOTHROW;
172 STATIC_CONTRACT_FORBID_FAULT;
175 UINT32 cbBlobContentSize;
177 // This should not be a necessary special case. The zero byte at the
178 // start of the pool will code for a length of zero. We will return
179 // a pointer to the next length byte, but the caller should notice that
180 // the size is zero, and should not look at any bytes.
181 // [SL] Yes, but we don't need all further computations and checks if iOffset==0
189 if (m_pSegData == m_zeros)
191 Debug_ReportError("Invalid blob offset.");
192 IfFailGo(CLDB_E_INDEX_NOTFOUND);
195 IfFailGo(GetDataReadOnly(nOffset, pData));
196 if (!pData->GetCompressedU(&cbBlobContentSize))
198 Debug_ReportError("Invalid blob - size compression.");
199 IfFailGo(CLDB_E_INDEX_NOTFOUND);
201 if (!pData->TruncateToExactSize(cbBlobContentSize))
203 Debug_ReportError("Invalid blob - reaches behind the end of data block.");
204 IfFailGo(CLDB_E_INDEX_NOTFOUND);
211 } // StgBlobPoolReadOnly::GetBlob