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//*****************************************************************************
5// RemoteMDInternalRWSource.cpp
6//
7
8//
9//*****************************************************************************
10
11#include "stdafx.h"
12#include "remotemdinternalrwsource.h"
13
14RemoteMDInternalRWSource::RemoteMDInternalRWSource() :
15m_cRef(0)
16{
17 memset(&m_TableDefs, 0, sizeof(CMiniTableDef)*TBL_COUNT);
18 memset(&m_bSortable, 0, sizeof(BOOL)*TBL_COUNT);
19}
20
21RemoteMDInternalRWSource::~RemoteMDInternalRWSource()
22{
23 for (int i = 0; i < TBL_COUNT; i++)
24 {
25 delete[] m_TableDefs[i].m_pColDefs;
26 }
27}
28
29ULONG RemoteMDInternalRWSource::AddRef()
30{
31 return InterlockedIncrement(&m_cRef);
32}
33
34ULONG RemoteMDInternalRWSource::Release()
35{
36 ULONG cRef = InterlockedDecrement(&m_cRef);
37 if (cRef == 0)
38 delete this;
39 return cRef;
40}
41
42HRESULT RemoteMDInternalRWSource::QueryInterface(REFIID riid, void ** ppUnk)
43{
44 *ppUnk = 0;
45 if (riid == IID_IUnknown)
46 {
47 *ppUnk = static_cast<IUnknown*>(this);
48 }
49 else if (riid == IID_IMDCustomDataSource)
50 {
51 *ppUnk = static_cast<IMDCustomDataSource*>(this);
52 }
53 else
54 {
55 return E_NOINTERFACE;
56 }
57 AddRef();
58 return S_OK;
59}
60
61HRESULT _MarshalDataFromTargetStgPool(DataTargetReader & reader, const Target_StgPool & pool, MetaData::DataBlob* pBlob)
62{
63 HRESULT hr = S_OK;
64 ULONG32 dataSize = 0;
65 ULONG32 segmentCount = 0;
66 Target_StgPoolSeg curSeg = (Target_StgPoolSeg)pool;
67
68 // The storage pool grows exponentially, and should reach 2GB in at most 64 segments. Allowing for 1000
69 // adds a sizable risk mitigation factor in case my analysis was inaccurate or the algorithm changes in the future
70 // without corresponding changes here.
71 CORDB_ADDRESS segmentData[1000];
72 ULONG32 segmentSize[1000];
73 for (; segmentCount < 1000; segmentCount++)
74 {
75 // sanity check that each segment and the sum of all segments is less than 100M bytes
76 if (curSeg.m_cbSegNext > 100000000)
77 return CLDB_E_FILE_CORRUPT;
78 dataSize += curSeg.m_cbSegNext;
79 if (dataSize > 100000000)
80 return CLDB_E_FILE_CORRUPT;
81 segmentData[segmentCount] = curSeg.m_pSegData;
82 segmentSize[segmentCount] = curSeg.m_cbSegNext;
83 if (curSeg.m_pNextSeg == 0)
84 break;
85
86 DataTargetReader segReader = reader.CreateReaderAt(curSeg.m_pNextSeg);
87 IfFailRet(segReader.Read(&curSeg));
88 }
89
90 //we exited the loop with a break, count should be one more than the last index
91 segmentCount++;
92
93 // sanity check, no more than 1000 segments allowed
94 if (segmentCount > 1000)
95 return CLDB_E_FILE_CORRUPT;
96
97 // things looked reasonable enough, marshal over the data
98 NewArrayHolder<BYTE> pData = new (nothrow) BYTE[dataSize];
99 if (pData == NULL)
100 return E_OUTOFMEMORY;
101 BYTE* pCursor = pData;
102 for (ULONG32 i = 0; i < segmentCount; i++)
103 {
104 DataTargetReader segDataReader = reader.CreateReaderAt(segmentData[i]);
105 hr = segDataReader.ReadBytes(pCursor, segmentSize[i]);
106 if (FAILED(hr))
107 {
108 return hr;
109 }
110 else
111 {
112 pCursor += segmentSize[i];
113 }
114 }
115 pBlob->Init(pData, dataSize);
116 pData.SuppressRelease(); // our caller owns the buffer now
117 return S_OK;
118
119}
120
121HRESULT RemoteMDInternalRWSource::InitFromTarget(TADDR remoteMDInternalRWAddr, ICorDebugDataTarget* pDataTarget, DWORD defines, DWORD dataStructureVersion)
122{
123 HRESULT hr = S_OK;
124 DataTargetReader reader(remoteMDInternalRWAddr, pDataTarget, defines, dataStructureVersion);
125 IfFailRet(reader.Read(&m_targetData));
126
127 Target_CMiniMdSchema targetSchema = m_targetData.m_pStgdb.m_MiniMd.m_Schema;
128 m_Schema.m_ulReserved = targetSchema.m_ulReserved;
129 m_Schema.m_major = targetSchema.m_major;
130 m_Schema.m_minor = targetSchema.m_minor;
131 m_Schema.m_heaps = targetSchema.m_heaps;
132 m_Schema.m_rid = targetSchema.m_rid;
133 m_Schema.m_maskvalid = targetSchema.m_maskvalid;
134 m_Schema.m_sorted = targetSchema.m_sorted;
135 memcpy(m_Schema.m_cRecs, targetSchema.m_cRecs, sizeof(ULONG32)*TBL_COUNT);
136 m_Schema.m_ulExtra = targetSchema.m_ulExtra;
137
138 for (int i = 0; i < TBL_COUNT; i++)
139 {
140 Target_CMiniTableDef* pTargetTableDef = &(m_targetData.m_pStgdb.m_MiniMd.m_TableDefs[i]);
141 m_TableDefs[i].m_cCols = pTargetTableDef->m_cCols;
142 m_TableDefs[i].m_iKey = pTargetTableDef->m_iKey;
143 m_TableDefs[i].m_cbRec = pTargetTableDef->m_cbRec;
144 m_TableDefs[i].m_pColDefs = new (nothrow) CMiniColDef[m_TableDefs[i].m_cCols];
145 if (m_TableDefs[i].m_pColDefs == NULL)
146 return E_OUTOFMEMORY;
147 for (int j = 0; j < m_TableDefs[i].m_cCols; j++)
148 {
149 m_TableDefs[i].m_pColDefs[j].m_Type = pTargetTableDef->m_pColDefs[j].m_Type;
150 m_TableDefs[i].m_pColDefs[j].m_oColumn = pTargetTableDef->m_pColDefs[j].m_oColumn;
151 m_TableDefs[i].m_pColDefs[j].m_cbColumn = pTargetTableDef->m_pColDefs[j].m_cbColumn;
152 }
153 }
154
155 IfFailRet(_MarshalDataFromTargetStgPool(reader, (Target_StgPool)m_targetData.m_pStgdb.m_MiniMd.m_StringHeap, &m_StringHeap));
156 m_StringHeapStorage = m_StringHeap.GetDataPointer();
157 IfFailRet(_MarshalDataFromTargetStgPool(reader, (Target_StgPool)m_targetData.m_pStgdb.m_MiniMd.m_BlobHeap, &m_BlobHeap));
158 m_BlobHeapStorage = m_BlobHeap.GetDataPointer();
159 IfFailRet(_MarshalDataFromTargetStgPool(reader, (Target_StgPool)m_targetData.m_pStgdb.m_MiniMd.m_UserStringHeap, &m_UserStringHeap));
160 m_UserStringHeapStorage = m_UserStringHeap.GetDataPointer();
161 IfFailRet(_MarshalDataFromTargetStgPool(reader, (Target_StgPool)m_targetData.m_pStgdb.m_MiniMd.m_GuidHeap, &m_GuidHeap));
162 m_GuidHeapStorage = m_GuidHeap.GetDataPointer();
163
164 for (int i = 0; i < TBL_COUNT; i++)
165 {
166 IfFailRet(_MarshalDataFromTargetStgPool(reader, (Target_StgPool)m_targetData.m_pStgdb.m_MiniMd.m_Tables[i], &m_TableRecords[i]));
167 m_TableRecordsStorage[i] = m_TableRecords[i].GetDataPointer();
168 m_bSortable[i] = m_targetData.m_pStgdb.m_MiniMd.m_bSortable[i];
169 }
170
171 if (m_targetData.m_pStgdb.m_pvMd != 0)
172 {
173 STORAGESIGNATURE sig = { 0 };
174 DataTargetReader storageSigReader = reader.CreateReaderAt(m_targetData.m_pStgdb.m_pvMd);
175 storageSigReader.ReadBytes((BYTE*)&sig, sizeof(sig));
176 if (sig.GetVersionStringLength() > 1000)
177 return CLDB_E_FILE_CORRUPT;
178 ULONG32 totalSigSize = offsetof(STORAGESIGNATURE, pVersion) + sig.GetVersionStringLength();
179 m_SigStorage = new (nothrow)BYTE[totalSigSize];
180 if (m_SigStorage == NULL)
181 return E_OUTOFMEMORY;
182 memcpy_s(m_SigStorage, totalSigSize, &sig, sizeof(sig));
183 storageSigReader.ReadBytes(m_SigStorage + sizeof(sig), totalSigSize - sizeof(sig));
184 m_Sig.Init(m_SigStorage, totalSigSize);
185 }
186
187 return S_OK;
188}
189
190STDMETHODIMP RemoteMDInternalRWSource::GetSchema(CMiniMdSchema* pSchema)
191{
192 *pSchema = m_Schema;
193 return S_OK;
194}
195STDMETHODIMP RemoteMDInternalRWSource::GetTableDef(ULONG32 tableIndex, CMiniTableDef* pTableDef)
196{
197 *pTableDef = m_TableDefs[tableIndex];
198 return S_OK;
199}
200
201STDMETHODIMP RemoteMDInternalRWSource::GetBlobHeap(MetaData::DataBlob* pBlobHeapData)
202{
203 *pBlobHeapData = m_BlobHeap;
204 return S_OK;
205}
206
207STDMETHODIMP RemoteMDInternalRWSource::GetGuidHeap(MetaData::DataBlob* pGuidHeapData)
208{
209 *pGuidHeapData = m_GuidHeap;
210 return S_OK;
211}
212
213STDMETHODIMP RemoteMDInternalRWSource::GetStringHeap(MetaData::DataBlob* pStringHeapData)
214{
215 *pStringHeapData = m_StringHeap;
216 return S_OK;
217}
218
219STDMETHODIMP RemoteMDInternalRWSource::GetUserStringHeap(MetaData::DataBlob* pUserStringHeapData)
220{
221 *pUserStringHeapData = m_UserStringHeap;
222 return S_OK;
223}
224
225STDMETHODIMP RemoteMDInternalRWSource::GetTableRecords(ULONG32 tableIndex, MetaData::DataBlob* pTableRecordData)
226{
227 *pTableRecordData = m_TableRecords[tableIndex];
228 return S_OK;
229}
230
231STDMETHODIMP RemoteMDInternalRWSource::GetTableSortable(ULONG32 tableIndex, BOOL* pSortable)
232{
233 *pSortable = TRUE;
234 return S_OK;
235}
236
237STDMETHODIMP RemoteMDInternalRWSource::GetStorageSignature(MetaData::DataBlob* pStorageSignature)
238{
239 *pStorageSignature = m_Sig;
240 return S_OK;
241}
242