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// DDMarshalUtil.cpp
6
7
8#ifndef _DDMarshal_Util_h
9#define _DDMarshal_Util_h
10
11#include "dacdbiinterface.h"
12typedef IDacDbiInterface::StackWalkHandle StackWalkHandle;
13typedef IDacDbiInterface::HeapWalkHandle HeapWalkHandle;
14typedef IDacDbiInterface::IStringHolder IStringHolder;
15
16#include "stringcopyholder.h"
17
18// @dbgtodo Mac - cleanup the buffer classes here. (are there pre-existing classes we could use instead?)
19// These ultimately get included in the signature for IDacDbiMarshalStub::DoRequest.
20// Key is that this helps serialize remote sized structures like IStringHolder and DacDbiArrayList<T>.
21class BaseBuffer
22{
23public:
24 BaseBuffer()
25 {
26 m_idx = 0;
27 m_pBuffer = NULL;
28 m_size = 0;
29 }
30
31protected:
32 DWORD m_idx;
33 DWORD m_size;
34 BYTE * m_pBuffer;
35};
36
37class WriteBuffer : public BaseBuffer
38{
39public:
40 friend class ReadBuffer;
41
42 WriteBuffer()
43 {
44 // @dbgtodo Mac - do something smarter than always allocate 1000 bytes.
45 m_size = 1000;
46 m_pBuffer = new BYTE[m_size];
47 }
48 ~WriteBuffer()
49 {
50 if (m_pBuffer != NULL)
51 {
52 delete [] m_pBuffer;
53 m_pBuffer = NULL;
54 }
55 }
56
57 // Write to the buffer, and grow if needed.
58 void WriteBlob(const void * pData, DWORD cbLength)
59 {
60 _ASSERTE(m_pBuffer != NULL);
61 EnsureSize(cbLength);
62 memcpy(&m_pBuffer[m_idx], pData, cbLength);
63 m_idx += cbLength;
64 }
65
66 void EnsureSize(DWORD cbLength)
67 {
68 DWORD cbSizeNeeded = m_idx + cbLength;
69 _ASSERTE(cbSizeNeeded <= 128000); // sanity checking...
70 while(cbSizeNeeded >= m_size)
71 {
72 DWORD cbNewSize = (m_size * 3) / 2; // grow by 1.5
73 BYTE * pNewBuffer = new BYTE[cbNewSize];
74 memcpy(pNewBuffer, m_pBuffer, m_idx);
75
76 _ASSERTE(m_pBuffer != NULL);
77 delete [] m_pBuffer;
78
79 m_size = cbNewSize;
80 m_pBuffer = pNewBuffer;
81 }
82 }
83
84 void WriteString(const WCHAR * pString)
85 {
86 bool fIsNull = (pString == NULL ? true : false);
87 EnsureSize(sizeof(fIsNull));
88 memcpy(&m_pBuffer[m_idx], &fIsNull, sizeof(fIsNull));
89 m_idx += sizeof(fIsNull);
90
91 if (!fIsNull)
92 {
93 _ASSERTE(pString != NULL);
94 DWORD len = (DWORD) wcslen(pString);
95 DWORD cbCopy = (len + 1) * sizeof(WCHAR);
96
97 EnsureSize(cbCopy);
98 memcpy(&m_pBuffer[m_idx], pString, cbCopy);
99 m_idx += cbCopy;
100 }
101 }
102
103 // Gets access to the raw buffer - does not transfer ownership of the memory
104 void GetRawPtr(PBYTE * ppBuffer, DWORD * pcbUsed)
105 {
106 *ppBuffer = m_pBuffer;
107 *pcbUsed = m_idx;
108 }
109};
110
111// Read-only stream access to memory blob.
112class ReadBuffer : public BaseBuffer
113{
114public:
115 ReadBuffer()
116 {
117 m_fDeleteOnClose = false;
118 }
119 ~ReadBuffer()
120 {
121 if (m_fDeleteOnClose)
122 {
123 delete [] m_pBuffer;
124 }
125 }
126
127 // Create on existing stream
128 void Open(BYTE * pStream, DWORD cbLength)
129 {
130 _ASSERTE(m_pBuffer == NULL);
131 _ASSERTE(m_idx == 0);
132 m_pBuffer = pStream;
133 m_size = cbLength;
134 }
135 void OpenAndOwn(BYTE * pStream, DWORD cbLength)
136 {
137 Open(pStream, cbLength);
138 m_fDeleteOnClose = true;
139 }
140
141 // Get a reader for the range written by a Writer
142 // This steal's the writer's buffer. The Writer object is dead after this.
143 void Open(WriteBuffer * pBuffer)
144 {
145 _ASSERTE(m_pBuffer == NULL);
146 _ASSERTE(m_idx == 0);
147 m_size = pBuffer->m_idx;
148 m_pBuffer = pBuffer->m_pBuffer;
149
150
151 pBuffer->m_pBuffer = NULL;
152 m_fDeleteOnClose = true;
153 }
154
155 bool IsAtEnd()
156 {
157 return (m_idx == m_size);
158 }
159 void ReadBlob(void * pData, DWORD cbLength)
160 {
161 _ASSERTE(m_idx + cbLength <= m_size);
162 memcpy(pData, &m_pBuffer[m_idx], cbLength);
163 m_idx += cbLength;
164 }
165 DWORD Length()
166 {
167 return m_size;
168 }
169
170 // Return a pointer to the string and mvoe the index.
171 const WCHAR * ReadString()
172 {
173 bool fIsNull = *reinterpret_cast<bool *>(&m_pBuffer[m_idx]);
174 m_idx += sizeof(fIsNull);
175
176 if (fIsNull)
177 {
178 return NULL;
179 }
180 else
181 {
182 const WCHAR * pString = (WCHAR*) &m_pBuffer[m_idx];
183 DWORD len = (DWORD) wcslen(pString);
184 m_idx += (len + 1) * sizeof(WCHAR); // skip past null
185 _ASSERTE(m_idx <= m_size);
186 return pString;
187 }
188 }
189
190protected:
191 bool m_fDeleteOnClose;
192};
193
194
195
196//
197// Writers
198//
199template<class T> inline
200void WriteToBuffer(WriteBuffer * p, T & data)
201{
202 p->WriteBlob(&data, sizeof(T));
203}
204
205inline
206void WriteToBuffer(WriteBuffer * p, StackWalkHandle & h)
207{
208 p->WriteBlob(&h, sizeof(StackWalkHandle));
209}
210
211inline
212void WriteCookie(WriteBuffer * p, BYTE cookie)
213{
214#if _DEBUG
215 WriteToBuffer(p, cookie);
216#endif
217}
218
219
220template<class T> inline
221void WriteToBuffer(WriteBuffer * p, T * pData)
222{
223 p->WriteBlob(pData, sizeof(T));
224}
225
226inline
227void WriteToBuffer(WriteBuffer * p, StringCopyHolder * pString)
228{
229 const WCHAR * pData = NULL;
230 if (pString->IsSet())
231 {
232 pData = *pString; // gets raw data
233 }
234 p->WriteString(pData);
235 WriteCookie(p, 0x1F);
236}
237
238template<class T> inline
239void WriteToBuffer(WriteBuffer * p, DacDbiArrayList<T> * pList)
240{
241 _ASSERTE(pList != NULL);
242 WriteCookie(p, 0xCD);
243
244 int count = pList->Count();
245 WriteToBuffer(p, count);
246
247 if (count == 0) return;
248
249 // Write raw data.
250 for(int i = 0; i < count; i++)
251 {
252 const T * pElement = &((*pList)[i]);
253 WriteToBuffer(p, pElement);
254 }
255 WriteCookie(p, 0xAB);
256}
257
258template<class T> inline
259void WriteToBuffer(WriteBuffer * p, DacDbiArrayList<T> & list)
260{
261 WriteToBuffer(p, &list);
262}
263
264inline
265void WriteToBuffer(WriteBuffer * p, NativeVarData * pData)
266{
267 WriteCookie(p, 0xD1);
268 p->WriteBlob(pData, sizeof(NativeVarData));
269 WriteToBuffer(p, pData->m_offsetInfo);
270}
271
272inline
273void WriteToBuffer(WriteBuffer * p, SequencePoints * pData)
274{
275 WriteCookie(p, 0xD2);
276 p->WriteBlob(pData, sizeof(SequencePoints));
277 WriteToBuffer(p, pData->m_map);
278}
279inline
280void WriteToBuffer(WriteBuffer * p, ClassInfo * pData)
281{
282 WriteCookie(p, 0xD3);
283 p->WriteBlob(pData, sizeof(ClassInfo));
284 WriteToBuffer(p, pData->m_fieldList);
285}
286
287//-----------------------------------------------------------------------------
288//
289// Readers
290//
291template<class T> inline
292void ReadFromBuffer(ReadBuffer * p, T & data)
293{
294 p->ReadBlob(&data, sizeof(T));
295}
296
297inline
298void ReadCookie(ReadBuffer * p, BYTE cookieExpected)
299{
300#if _DEBUG
301 BYTE cookie;
302 ReadFromBuffer(p, cookie);
303 _ASSERTE(cookie = cookieExpected);
304#endif
305}
306
307
308inline
309void ReadFromBuffer(ReadBuffer * p, StackWalkHandle & h)
310{
311 p->ReadBlob(&h, sizeof(StackWalkHandle));
312}
313
314template<class T> inline
315void ReadFromBuffer(ReadBuffer * p, T * pData)
316{
317 // Used to copy-back a By-ref / out parameter
318 p->ReadBlob(pData, sizeof(T));
319}
320
321inline
322void ReadFromBuffer(ReadBuffer * p, IStringHolder * pString)
323{
324 const WCHAR *pData = p->ReadString();
325 // AssignCopy() can handle a NULL string.
326 pString->AssignCopy(pData);
327 ReadCookie(p, 0x1F);
328}
329
330template<class T> inline
331void ReadFromBuffer(ReadBuffer * p, DacDbiArrayList<T> * pList)
332{
333 _ASSERTE(pList != NULL);
334
335 ReadCookie(p, 0xCD);
336
337 // Alloc() will attempt to free the old pointer.
338 // if this was blit copied, the pointer is trashed. So we need to safely clear that
339 // pointer to prepare it to be copied.
340 pList->PrepareForDeserialize();
341
342 int count;
343 ReadFromBuffer(p, count);
344
345 pList->Alloc(count);
346 if (count == 0)
347 {
348 return;
349 }
350
351 // Read raw data.
352 for(int i = 0; i < count; i++)
353 {
354 T * pElement = &((*pList)[i]);
355 ReadFromBuffer(p, pElement);
356 }
357 ReadCookie(p, 0xAB);
358}
359
360template<class T> inline
361void ReadFromBuffer(ReadBuffer * p, DacDbiArrayList<T> & list)
362{
363 ReadFromBuffer(p, &list);
364}
365
366inline
367void ReadFromBuffer(ReadBuffer * p, NativeVarData * pData)
368{
369 ReadCookie(p, 0xD1);
370 p->ReadBlob(pData, sizeof(NativeVarData));
371 ReadFromBuffer(p, &pData->m_offsetInfo);
372}
373
374inline
375void ReadFromBuffer(ReadBuffer * p, SequencePoints * pData)
376{
377 ReadCookie(p, 0xD2);
378 p->ReadBlob(pData, sizeof(SequencePoints));
379 ReadFromBuffer(p, &pData->m_map);
380}
381
382inline
383void ReadFromBuffer(ReadBuffer * p, ClassInfo * pData)
384{
385 ReadCookie(p, 0xD3);
386 p->ReadBlob(pData, sizeof(ClassInfo));
387 ReadFromBuffer(p, &pData->m_fieldList);
388}
389
390
391
392
393#endif // _DDMarshal_Util_h
394
395