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// MetaModel.h -- header file for compressed COM+ metadata.
6//
7
8//
9//*****************************************************************************
10#ifndef _METAMODEL_H_
11#define _METAMODEL_H_
12
13#if _MSC_VER >= 1100
14#pragma once
15#endif
16
17#include <cor.h>
18#include <stgpool.h>
19#include <metamodelpub.h>
20#include "metadatatracker.h"
21
22#include "../datablob.h"
23#include "../debug_metadata.h"
24
25#undef __unaligned
26
27#define ALLOCATED_MEMORY_MARKER 0xff
28
29// Version numbers for metadata format.
30
31#define METAMODEL_MAJOR_VER_V1_0 1 // Major version for v1.0
32#define METAMODEL_MINOR_VER_V1_0 0 // Minor version for v1.0
33
34#define METAMODEL_MAJOR_VER_V2_0 2 // Major version for v2.0
35#define METAMODEL_MINOR_VER_V2_0 0 // Minor version for v2.0
36
37#define METAMODEL_MAJOR_VER 2
38#define METAMODEL_MINOR_VER 0
39
40// Metadata version number up through Whidbey Beta2
41#define METAMODEL_MAJOR_VER_B1 1
42#define METAMODEL_MINOR_VER_B1 1
43
44
45typedef enum MetadataVersion
46{
47 MDVersion1 = 0x00000001,
48 MDVersion2 = 0x00000002,
49
50 // @TODO - this value should be updated when we increase the version number
51 MDDefaultVersion = 0x00000002
52} MetadataVersion;
53
54
55
56struct HENUMInternal;
57extern const CCodedTokenDef g_CodedTokens[CDTKN_COUNT];
58extern const CMiniTableDefEx g_Tables[TBL_COUNT]; // The table definitions.
59
60struct TblCol
61{
62 ULONG m_ixtbl; // Table ID.
63 ULONG m_ixcol; // Column ID.
64};
65extern TblCol g_PtrTableIxs[TBL_COUNT];
66
67// This abstract defines the common functions that can be used for RW and RO internally
68// (The primary user for this is Compiler\ImportHelper.cpp)
69class IMetaModelCommon
70{
71public:
72 __checkReturn
73 virtual HRESULT CommonGetScopeProps(
74 LPCUTF8 *pszName,
75 GUID *pMvid) = 0;
76
77 __checkReturn
78 virtual HRESULT CommonGetTypeRefProps(
79 mdTypeRef tr,
80 LPCUTF8 *pszNamespace,
81 LPCUTF8 *pszName,
82 mdToken *ptkResolution) = 0;
83
84 __checkReturn
85 virtual HRESULT CommonGetTypeDefProps(
86 mdTypeDef td,
87 LPCUTF8 *pszNameSpace,
88 LPCUTF8 *pszName,
89 DWORD *pdwFlags,
90 mdToken *pdwExtends,
91 ULONG *pMethodList) = 0;
92
93 __checkReturn
94 virtual HRESULT CommonGetTypeSpecProps(
95 mdTypeSpec ts,
96 PCCOR_SIGNATURE *ppvSig,
97 ULONG *pcbSig) = 0;
98
99 __checkReturn
100 virtual HRESULT CommonGetEnclosingClassOfTypeDef(
101 mdTypeDef td,
102 mdTypeDef *ptkEnclosingTypeDef) = 0;
103
104 __checkReturn
105 virtual HRESULT CommonGetAssemblyProps(
106 USHORT *pusMajorVersion,
107 USHORT *pusMinorVersion,
108 USHORT *pusBuildNumber,
109 USHORT *pusRevisionNumber,
110 DWORD *pdwFlags,
111 const void **ppbPublicKey,
112 ULONG *pcbPublicKey,
113 LPCUTF8 *pszName,
114 LPCUTF8 *pszLocale) = 0;
115
116 __checkReturn
117 virtual HRESULT CommonGetAssemblyRefProps(
118 mdAssemblyRef tkAssemRef,
119 USHORT *pusMajorVersion,
120 USHORT *pusMinorVersion,
121 USHORT *pusBuildNumber,
122 USHORT *pusRevisionNumber,
123 DWORD *pdwFlags,
124 const void **ppbPublicKeyOrToken,
125 ULONG *pcbPublicKeyOrToken,
126 LPCUTF8 *pszName,
127 LPCUTF8 *pszLocale,
128 const void **ppbHashValue,
129 ULONG *pcbHashValue) = 0;
130
131 __checkReturn
132 virtual HRESULT CommonGetModuleRefProps(
133 mdModuleRef tkModuleRef,
134 LPCUTF8 *pszName) = 0;
135
136 __checkReturn
137 virtual HRESULT CommonFindExportedType(
138 LPCUTF8 szNamespace,
139 LPCUTF8 szName,
140 mdToken tkEnclosingType,
141 mdExportedType *ptkExportedType) = 0;
142
143 __checkReturn
144 virtual HRESULT CommonGetExportedTypeProps(
145 mdToken tkExportedType,
146 LPCUTF8 *pszNamespace,
147 LPCUTF8 *pszName,
148 mdToken *ptkImpl) = 0;
149
150 virtual int CommonIsRo() = 0;
151
152 __checkReturn
153 virtual HRESULT CommonGetCustomAttributeByName( // S_OK or error.
154 mdToken tkObj, // [IN] Object with Custom Attribute.
155 LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
156 const void **ppData, // [OUT] Put pointer to data here.
157 ULONG *pcbData) // [OUT] Put size of data here.
158 {
159 return CommonGetCustomAttributeByNameEx(tkObj, szName, NULL, ppData, pcbData);
160 }
161
162 __checkReturn
163 virtual HRESULT CommonGetCustomAttributeByNameEx( // S_OK or error.
164 mdToken tkObj, // [IN] Object with Custom Attribute.
165 LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
166 mdCustomAttribute *ptkCA, // [OUT] put custom attribute token here
167 const void **ppData, // [OUT] Put pointer to data here.
168 ULONG *pcbData) = 0; // [OUT] Put size of data here.
169
170 __checkReturn
171 virtual HRESULT FindParentOfMethodHelper(mdMethodDef md, mdTypeDef *ptd) = 0;
172
173}; // class IMetaModelCommon
174
175
176
177// An extension of IMetaModelCommon, exposed by read-only importers only.
178// (The primary user for this is the WinMD import adapter which needs
179// a unified view of RegMeta and MDInternalRO.)
180//
181// These methods were separated from IMetaModelCommon as they are only used by
182// the WinMDAdapter and we don't want the maintainence and code-coverage cost
183// of providing Enc-aware versions of these methods.
184class IMetaModelCommonRO : public IMetaModelCommon
185{
186public:
187 virtual HRESULT CommonGetMethodDefProps(
188 mdMethodDef tkMethodDef,
189 LPCUTF8 *pszName,
190 DWORD *pdwFlags,
191 PCCOR_SIGNATURE *ppvSigBlob,
192 ULONG *pcbSigBlob
193 ) = 0;
194
195 virtual HRESULT CommonGetMemberRefProps(
196 mdMemberRef tkMemberRef,
197 mdToken *pParentToken
198 ) = 0;
199
200 virtual ULONG CommonGetRowCount( // return hresult
201 DWORD tkKind) = 0; // [IN] pass in the kind of token.
202
203 virtual HRESULT CommonGetMethodImpls(
204 mdTypeDef tkTypeDef, // [IN] typeDef to scope search
205 mdToken *ptkMethodImplFirst, // [OUT] returns first methodImpl token
206 ULONG *pMethodImplCount // [OUT] returns # of methodImpl tokens scoped to type
207 ) = 0;
208
209 virtual HRESULT CommonGetMethodImplProps(
210 mdToken tkMethodImpl, // [IN] methodImpl
211 mdToken *pBody, // [OUT] returns body token
212 mdToken *pDecl // [OUT] returns decl token
213 ) = 0;
214
215 virtual HRESULT CommonGetCustomAttributeProps(
216 mdCustomAttribute cv, // [IN] CustomAttribute token.
217 mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here.
218 mdToken *ptkType, // [OUT, OPTIONAL] Put AttrType token here.
219 const void **ppBlob, // [OUT, OPTIONAL] Put pointer to data here.
220 ULONG *pcbSize) = 0; // [OUT, OPTIONAL] Put size of date here.
221
222 virtual HRESULT CommonGetFieldDefProps(
223 mdFieldDef tkFieldDef,
224 mdTypeDef *ptkParent,
225 LPCUTF8 *pszName,
226 DWORD *pdwFlags
227 ) = 0;
228}; // class IMetaModelCommonRO
229
230
231//*****************************************************************************
232// The mini, hard-coded schema. For each table, we persist the count of
233// records. We also persist the size of string, blob, guid, and rid
234// columns. From this information, we can calculate the record sizes, and
235// then the sizes of the tables.
236//*****************************************************************************
237
238class CMiniMdSchemaBase
239{
240public:
241 ULONG m_ulReserved; // Reserved, must be zero.
242 BYTE m_major; // Version numbers.
243 BYTE m_minor;
244 BYTE m_heaps; // Bits for heap sizes.
245 BYTE m_rid; // log-base-2 of largest rid.
246
247 // Bits for heap sizes.
248 enum {
249 HEAP_STRING_4 = 0x01,
250 HEAP_GUID_4 = 0x02,
251 HEAP_BLOB_4 = 0x04,
252
253 PADDING_BIT = 0x08, // Tables can be created with an extra bit in columns, for growth.
254
255 DELTA_ONLY = 0x20, // If set, only deltas were persisted.
256 EXTRA_DATA = 0x40, // If set, schema persists an extra 4 bytes of data.
257 HAS_DELETE = 0x80, // If set, this metadata can contain _Delete tokens.
258 };
259
260 unsigned __int64 m_maskvalid; // Bit mask of present table counts.
261
262 unsigned __int64 m_sorted; // Bit mask of sorted tables.
263 FORCEINLINE bool IsSorted(ULONG ixTbl)
264 { return m_sorted & BIT(ixTbl) ? true : false; }
265 void SetSorted(ULONG ixTbl, int bVal)
266 { if (bVal) m_sorted |= BIT(ixTbl);
267 else m_sorted &= ~BIT(ixTbl); }
268
269#if BIGENDIAN
270 // Verify that the size hasn't changed (Update if necessary)
271 void ConvertEndianness()
272 {
273 _ASSERTE(sizeof(CMiniMdSchemaBase) == 0x18);
274 m_ulReserved = VAL32(m_ulReserved);
275 m_maskvalid = VAL64(m_maskvalid);
276 m_sorted = VAL64(m_sorted);
277 }
278#else
279 // Nothing to do on little endian machine
280 void ConvertEndianness() {return ;}
281#endif
282
283private:
284 FORCEINLINE unsigned __int64 BIT(ULONG ixBit)
285 { _ASSERTE(ixBit < (sizeof(__int64)*CHAR_BIT));
286 return UI64(1) << ixBit; }
287
288};
289
290class CMiniMdSchema : public CMiniMdSchemaBase
291{
292public:
293 // These are not all persisted to disk. See LoadFrom() for details.
294 ULONG m_cRecs[TBL_COUNT]; // Counts of various tables.
295
296 ULONG m_ulExtra; // Extra data, only persisted if non-zero. (m_heaps&EXTRA_DATA flags)
297
298 ULONG LoadFrom(const void*, ULONG); // Load from a compressed version. Return bytes consumed.
299 ULONG SaveTo(void *); // Store a compressed version. Return bytes used in buffer.
300 __checkReturn
301 HRESULT InitNew(MetadataVersion);
302};
303
304//*****************************************************************************
305// Helper macros and inline functions for navigating through the data. Many
306// of the macros are used to define inline accessor functions. Everything
307// is based on the naming conventions outlined at the top of the file.
308//*****************************************************************************
309#define _GETTER(tbl,fld) get##fld##Of##tbl(tbl##Rec *pRec)
310#define _GETTER2(tbl,fld,x) get##fld##Of##tbl(tbl##Rec *pRec, x)
311#define _GETTER3(tbl,fld,x,y) get##fld##Of##tbl(tbl##Rec *pRec, x, y)
312#define _GETTER4(tbl,fld,x,y,z) get##fld##Of##tbl(tbl##Rec *pRec, x, y,z)
313
314// Direct getter for a field. Defines an inline function like:
315// getSomeFieldOfXyz(XyzRec *pRec) { return pRec->m_SomeField;}
316// Note that the returned value declaration is NOT included.
317#if METADATATRACKER_ENABLED
318#define _GETFLD(tbl,fld) _GETTER(tbl,fld){ PVOID pVal = (BYTE*)pRec + offsetof(tbl##Rec, m_##fld); \
319 pVal = MetaDataTracker::NoteAccess(pVal); \
320 return ((tbl##Rec*)((BYTE*)pVal - offsetof(tbl##Rec, m_##fld)))->Get##fld(); }
321#else
322#define _GETFLD(tbl,fld) _GETTER(tbl,fld){ return pRec->Get##fld();}
323#endif
324
325// These functions call the helper function getIX to get a two or four byte value from a record,
326// and then use that value as an index into the appropriate pool.
327// getSomeFieldOfXyz(XyzRec *pRec) { return m_pStrings->GetString(getIX(pRec, _COLDEF(tbl,fld))); }
328// Note that the returned value declaration is NOT included.
329
330// Column definition of a field: Looks like:
331// m_XyzCol[XyzRec::COL_SomeField]
332#define _COLDEF(tbl,fld) m_TableDefs[TBL_##tbl].m_pColDefs[tbl##Rec::COL_##fld]
333#define _COLPAIR(tbl,fld) _COLDEF(tbl,fld), tbl##Rec::COL_##fld
334// Size of a record.
335#define _CBREC(tbl) m_TableDefs[TBL_##tbl].m_cbRec
336// Count of records in a table.
337#define _TBLCNT(tbl) m_Schema.m_cRecs[TBL_##tbl]
338
339#define _GETSTRA(tbl,fld) _GETTER2(tbl, fld, LPCSTR *pszString) \
340{ return getString(getI4(pRec, _COLDEF(tbl,fld)) & m_iStringsMask, pszString); }
341
342#define _GETSTRW(tbl,fld) _GETTER4(tbl, fld, LPWSTR szOut, ULONG cchBuffer, ULONG *pcchBuffer) \
343{ return getStringW(getI4(pRec, _COLDEF(tbl,fld)) & m_iStringsMask, szOut, cchBuffer, pcchBuffer); }
344
345#define _GETSTR(tbl, fld) \
346 __checkReturn HRESULT _GETSTRA(tbl, fld); \
347 __checkReturn HRESULT _GETSTRW(tbl, fld);
348
349
350#define _GETGUID(tbl,fld) _GETTER2(tbl,fld,GUID *pGuid) \
351{ return getGuid(getI4(pRec, _COLDEF(tbl,fld)) & m_iGuidsMask, pGuid); }
352
353#define _GETBLOB(tbl,fld) __checkReturn HRESULT _GETTER3(tbl,fld,const BYTE **ppbData,ULONG *pcbSize) \
354{ \
355 MetaData::DataBlob data; \
356 HRESULT hr = getBlob(getI4(pRec, _COLDEF(tbl,fld)) & m_iBlobsMask, &data); \
357 *ppbData = data.GetDataPointer(); \
358 *pcbSize = (ULONG)data.GetSize(); \
359 return hr; \
360}
361
362#define _GETSIGBLOB(tbl,fld) __checkReturn HRESULT _GETTER3(tbl,fld,PCCOR_SIGNATURE *ppbData,ULONG *pcbSize) \
363{ \
364 MetaData::DataBlob data; \
365 HRESULT hr = getBlob(getI4(pRec, _COLDEF(tbl,fld)) & m_iBlobsMask, &data); \
366 *ppbData = (PCCOR_SIGNATURE)data.GetDataPointer(); \
367 *pcbSize = (ULONG)data.GetSize(); \
368 return hr; \
369}
370
371// Like the above functions, but just returns the RID, not a looked-up value.
372#define _GETRID(tbl,fld) _GETTER(tbl,fld) \
373{ return getIX(pRec, _COLDEF(tbl,fld)); }
374
375// Like a RID, but turn into an actual token.
376#define _GETTKN(tbl,fld,tok) _GETTER(tbl,fld) \
377{ return TokenFromRid(getIX(pRec, _COLDEF(tbl,fld)), tok); }
378
379// Get a coded token.
380#define _GETCDTKN(tbl,fld,toks) _GETTER(tbl,fld) \
381{ return decodeToken(getIX(pRec, _COLDEF(tbl,fld)), toks, sizeof(toks)/sizeof(toks[0])); }
382
383// Functions for the start and end of a list.
384#define _GETLIST(tbl,fld,tbl2) \
385 RID _GETRID(tbl,fld); \
386 __checkReturn HRESULT getEnd##fld##Of##tbl(RID nRowIndex, RID *pEndRid) { return getEndRidForColumn(TBL_##tbl, nRowIndex, _COLDEF(tbl,fld), TBL_##tbl2, pEndRid); }
387
388
389#define BYTEARRAY_TO_COLDES(bytearray) (CMiniColDef*)((bytearray) + 1)
390#define COLDES_TO_BYTEARRAY(coldes) (((BYTE*)(coldes))-1)
391
392
393//*****************************************************************************
394// Base class for the MiniMd. This class provides the schema to derived
395// classes. It defines some virtual functions for access to data, suitable
396// for use by functions where utmost performance is NOT a requirement.
397// Finally, it provides some searching functions, built on the virtual
398// data access functions (it is here assumed that if we are searching a table
399// for some value, the cost of a virtual function call is acceptable).
400// Some static utility functions and associated static data, shared across
401// implementations, is provided here.
402//
403// NB: It's unfortunate that CMiniMDBase "implements" IMetaModelCommonRO rather
404// than IMetaModelCommon, as methods on IMetaModelCommonRO are by definition,
405// not Enc-aware. Ideally, CMiniMDBase should only implement IMetaModelCommon
406// and CMiniMd should be the one implementing IMetaModelCommonRO.
407//
408// To make that happen would be a substantial refactoring job as RegMeta
409// always embeds CMiniMdRW even when it was opened for ReadOnly.
410//*****************************************************************************
411class CMiniMdBase : public IMetaModelCommonRO
412{
413
414 friend class VerifyLayoutsMD; // verifies class layout doesn't accidentally change
415
416public:
417 CMiniMdBase();
418 ~CMiniMdBase();
419 __checkReturn
420 virtual HRESULT vGetRow(UINT32 nTableIndex, UINT32 nRowIndex, void **ppRow) = 0;
421 ULONG GetCountRecs(ULONG ixTbl);
422 ULONG GetCountTables() { return m_TblCount;}
423
424 // Search a table for the row containing the given key value.
425 // EG. Constant table has pointer back to Param or Field.
426 __checkReturn
427 virtual HRESULT vSearchTable( // RID of matching row, or 0.
428 ULONG ixTbl, // Table to search.
429 CMiniColDef sColumn, // Sorted key column, containing search value.
430 ULONG ulTarget, // Target for search.
431 RID *pRid) = 0;
432
433 // Search a table for the highest-RID row containing a value that is less than
434 // or equal to the target value. EG. TypeDef points to first Field, but if
435 // a TypeDef has no fields, it points to first field of next TypeDef.
436 __checkReturn
437 virtual HRESULT vSearchTableNotGreater( // RID of matching row, or 0.
438 ULONG ixTbl, // Table to search.
439 CMiniColDef sColumn, // the column def containing search value
440 ULONG ulTarget, // target for search
441 RID *pRid) = 0;
442
443 // Search a table for multiple (adjacent) rows containing the given
444 // key value. EG, InterfaceImpls all point back to the implementing class.
445 __checkReturn
446 HRESULT SearchTableForMultipleRows( // First RID found, or 0.
447 ULONG ixTbl, // Table to search.
448 CMiniColDef sColumn, // Sorted key column, containing search value.
449 ULONG ulTarget, // Target for search.
450 RID *pEnd, // [OPTIONAL, OUT]
451 RID *pFoundRid);
452
453 // Search for a custom value with a given type.
454 __checkReturn
455 HRESULT FindCustomAttributeFor(// RID of custom value, or 0.
456 RID rid, // The object's rid.
457 mdToken tkOjb, // The object's type.
458 mdToken tkType, // Type of custom value.
459 RID *pFoundRid);
460
461 // Search for the specified Column Definition array in the global cache
462 BOOL FindSharedColDefs(// TRUE if we found a match in the global cache and updated pTable, FALSE otherwise
463 CMiniTableDef *pTable, // The table def that wants the column definition array
464 CMiniColDef *pColsToMatch, // The columns that we need to match
465 DWORD ixTbl);
466
467 // Return RID to EventMap table, given the rid to a TypeDef.
468 __checkReturn
469 HRESULT FindEventMapFor(RID ridParent, RID *pFoundRid);
470
471 // Return RID to PropertyMap table, given the rid to a TypeDef.
472 __checkReturn
473 HRESULT FindPropertyMapFor(RID ridParent, RID *pFoundRid);
474
475#if BIGENDIAN
476 // Swap a constant
477 __checkReturn
478 HRESULT SwapConstant(const void *pBlobValue, DWORD dwType, VOID *pConstant, ULONG BlobLength);
479#endif
480
481 // Pull two or four bytes out of a record.
482 inline static ULONG getIX(const void *pRec, CMiniColDef &def)
483 {
484 PVOID pVal = (BYTE *)pRec + def.m_oColumn;
485 if (def.m_cbColumn == 2)
486 {
487 METADATATRACKER_ONLY(pVal = MetaDataTracker::NoteAccess(pVal));
488 ULONG ix = GET_UNALIGNED_VAL16(pVal);
489 return ix;
490 }
491 _ASSERTE(def.m_cbColumn == 4);
492 METADATATRACKER_ONLY(pVal = MetaDataTracker::NoteAccess(pVal));
493 return GET_UNALIGNED_VAL32(pVal);
494 }
495
496 inline static ULONG getIX_NoLogging(const void *pRec, CMiniColDef &def)
497 {
498 PVOID pVal = (BYTE *)pRec + def.m_oColumn;
499 if (def.m_cbColumn == 2)
500 {
501 ULONG ix = GET_UNALIGNED_VAL16(pVal);
502 return ix;
503 }
504 _ASSERTE(def.m_cbColumn == 4);
505 return GET_UNALIGNED_VAL32(pVal);
506 }
507
508 // Pull four bytes out of a record.
509 FORCEINLINE static ULONG getI1(const void *pRec, CMiniColDef &def)
510 {
511 PVOID pVal = (BYTE *)pRec + def.m_oColumn;
512 METADATATRACKER_ONLY(pVal = MetaDataTracker::NoteAccess(pVal));
513 return *(BYTE*)pVal;
514 }
515
516 // Pull four bytes out of a record.
517 FORCEINLINE static ULONG getI4(const void *pRec, CMiniColDef &def)
518 {
519 PVOID pVal = (BYTE *)pRec + def.m_oColumn;
520 METADATATRACKER_ONLY(pVal = MetaDataTracker::NoteAccess(pVal));
521 return GET_UNALIGNED_VAL32(pVal);
522 }
523
524 // Function to encode a token into fewer bits. Looks up token type in array of types.
525 ULONG static encodeToken(RID rid, mdToken typ, const mdToken rTokens[], ULONG32 cTokens);
526
527 // Decode a token.
528 inline static mdToken decodeToken(mdToken val, const mdToken rTokens[], ULONG32 cTokens)
529 {
530 //<TODO>@FUTURE: make compile-time calculation</TODO>
531 ULONG32 ix = (ULONG32)(val & ~(-1 << m_cb[cTokens]));
532 // If the coded token has an invalid table index, return the first entry
533 // from the array of valid token types. It would be preferable to
534 // return an error or to raise an exception.
535 if (ix >= cTokens)
536 return rTokens[0];
537 return TokenFromRid(val >> m_cb[cTokens], rTokens[ix]);
538 }
539 static const int m_cb[];
540
541 // Given a token, what table does it live in?
542 inline ULONG GetTblForToken(mdToken tk)
543 {
544 tk = TypeFromToken(tk);
545 return (tk < mdtString) ? tk >> 24 : (ULONG) -1;
546 }
547
548 //*****************************************************************************
549 // Returns whether the data has been verified, which means it was verified by a
550 // trusted source and has not changed.
551 //
552 // If so, this means the following aspects of the data can be trusted as accurate:
553 // - m_Schema.IsSorted[TBL_PropertyMap] reflects whether that table is sorted by Parent (see CMiniMdRW::PreSaveFull)
554 // - m_Schema.IsSorted[TBL_EventMap] reflects whether that table is sorted by Parent (see CMiniMdRW::PreSaveFull)
555 //
556 // Currently, metadata saved in NGen images is the only trusted source.
557 //*****************************************************************************
558 BOOL IsVerified()
559 {
560 return m_fVerifiedByTrustedSource && CommonIsRo();
561 }
562
563 void SetVerifiedByTrustedSource(BOOL fVerifiedByTrustedSource)
564 {
565 m_fVerifiedByTrustedSource = fVerifiedByTrustedSource;
566 }
567
568 STDMETHODIMP GetRvaOffsetData(// S_OK or error
569 DWORD *pFirstMethodRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in MethodDef table.
570 DWORD *pMethodDefRecordSize, // [OUT] Size of each record in MethodDef table.
571 DWORD *pMethodDefCount, // [OUT] Number of records in MethodDef table.
572 DWORD *pFirstFieldRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in FieldRVA table.
573 DWORD *pFieldRvaRecordSize, // [OUT] Size of each record in FieldRVA table.
574 DWORD *pFieldRvaCount) // [OUT] Number of records in FieldRVA table.
575 {
576 _ASSERTE("Not implemented");
577 return E_NOTIMPL;
578 }
579
580 //*****************************************************************************
581 // Some of the tables need coded tokens, not just rids (ie, the column can
582 // refer to more than one other table). Code the tokens into as few bits
583 // as possible, by using 1, 2, 3, etc., bits to code the token type, then
584 // use that value to index into an array of token types.
585 //*****************************************************************************
586 static const mdToken mdtTypeDefOrRef[3];
587 static const mdToken mdtHasConstant[3];
588 static const mdToken mdtHasCustomAttribute[24];
589 static const mdToken mdtHasFieldMarshal[2];
590 static const mdToken mdtHasDeclSecurity[3];
591 static const mdToken mdtMemberRefParent[5];
592 static const mdToken mdtHasSemantic[2];
593 static const mdToken mdtMethodDefOrRef[2];
594 static const mdToken mdtMemberForwarded[2];
595 static const mdToken mdtImplementation[3];
596 static const mdToken mdtCustomAttributeType[5];
597 static const mdToken mdtResolutionScope[4];
598 static const mdToken mdtTypeOrMethodDef[2];
599
600
601public:
602 virtual BOOL IsWritable() = 0;
603
604
605protected:
606 CMiniMdSchema m_Schema; // data header.
607 ULONG m_TblCount; // Tables in this database.
608 BOOL m_fVerifiedByTrustedSource; // whether the data was verified by a trusted source
609
610 // Declare CMiniColDefs for every table. They look like either:
611 // static const BYTE s_xyz[];
612 // or
613 // static const BYTE* s_xyz;
614
615 #include "mdcolumndescriptors.h"
616
617 static const BYTE* const s_TableColumnDescriptors[TBL_COUNT];
618 CMiniTableDef m_TableDefs[TBL_COUNT];
619
620 ULONG m_iStringsMask;
621 ULONG m_iGuidsMask;
622 ULONG m_iBlobsMask;
623
624 __checkReturn
625 HRESULT SchemaPopulate(const void *pvData, ULONG cbData, ULONG *pcbUsed);
626 __checkReturn
627 HRESULT SchemaPopulate(const CMiniMdBase &that);
628 __checkReturn
629 HRESULT InitColsForTable(CMiniMdSchema &Schema, int ixTbl, CMiniTableDef *pTable, int bExtra, BOOL fUsePointers);
630 __checkReturn
631 HRESULT SchemaPopulate2(ULONG *pcbTables, int bExtra=false);
632 const CMiniTableDef* GetTableDefTemplate(int ixTbl);
633 __checkReturn
634 HRESULT SetNewColumnDefinition(CMiniTableDef *pTable, CMiniColDef* pCols, DWORD ixTbl);
635
636private:
637
638 BOOL UsesAllocatedMemory(CMiniColDef* pCols);
639};
640
641
642#ifdef FEATURE_METADATA_RELEASE_MEMORY_ON_REOPEN
643#define MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED() MarkUnsafeToDelete()
644#else
645#define MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED()
646#endif
647
648//*****************************************************************************
649// This class defines the interface to the MiniMd. The template parameter is
650// a derived class which provides implementations for a few primitives that
651// the interface is built upon.
652// To use, declare a class:
653// class CMyMiniMd : public CMiniMdTemplate<CMyMiniMd> {...};
654// and provide implementations of the primitives. Any non-trivial
655// implementation will also provide initialization, and probably serialization
656// functions as well.
657//*****************************************************************************
658template <class Impl> class CMiniMdTemplate : public CMiniMdBase
659{
660#ifdef FEATURE_METADATA_RELEASE_MEMORY_ON_REOPEN
661protected:
662 CMiniMdTemplate() : m_isSafeToDelete(TRUE) { }
663#endif
664
665 // Primitives -- these must be implemented in the Impl class.
666public:
667 __checkReturn
668 FORCEINLINE HRESULT getString(UINT32 nIndex, __out LPCSTR *pszString)
669 {
670 MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED();
671 return static_cast<Impl*>(this)->Impl_GetString(nIndex, pszString);
672 }
673 __checkReturn
674 FORCEINLINE HRESULT getStringW(ULONG nIndex, __inout_ecount (cchBuffer) LPWSTR szOut, ULONG cchBuffer, ULONG *pcchBuffer)
675 {
676 MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED();
677 return static_cast<Impl*>(this)->Impl_GetStringW(nIndex, szOut, cchBuffer, pcchBuffer);
678 }
679 __checkReturn
680 FORCEINLINE HRESULT getGuid(UINT32 nIndex, GUID *pGuid)
681 {
682 MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED();
683 return static_cast<Impl*>(this)->Impl_GetGuid(nIndex, pGuid);
684 }
685 __checkReturn
686 FORCEINLINE HRESULT getBlob(UINT32 nIndex, __out MetaData::DataBlob *pData)
687 {
688 MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED();
689 return static_cast<Impl*>(this)->Impl_GetBlob(nIndex, pData);
690 }
691 __checkReturn
692 FORCEINLINE HRESULT getRow(UINT32 nTableIndex, UINT32 nRowIndex, __deref_out void **ppRow)
693 {
694 MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED();
695 return static_cast<Impl*>(this)->Impl_GetRow(nTableIndex, nRowIndex, reinterpret_cast<BYTE **>(ppRow));
696 }
697 __checkReturn
698 FORCEINLINE HRESULT getEndRidForColumn(
699 UINT32 nTableIndex,
700 RID nRowIndex,
701 CMiniColDef &columnDefinition,
702 UINT32 nTargetTableIndex,
703 __out RID *pEndRid)
704 {
705 MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED();
706 return static_cast<Impl*>(this)->Impl_GetEndRidForColumn(nTableIndex, nRowIndex, columnDefinition, nTargetTableIndex, pEndRid);
707 }
708 __checkReturn
709 FORCEINLINE HRESULT doSearchTable(ULONG ixTbl, CMiniColDef sColumn, ULONG ixColumn, ULONG ulTarget, RID *pFoundRid)
710 {
711 MINIMD_POSSIBLE_INTERNAL_POINTER_EXPOSED();
712 return static_cast<Impl*>(this)->Impl_SearchTable(ixTbl, sColumn, ixColumn, ulTarget, pFoundRid);
713 }
714
715 // IMetaModelCommonRO interface beginning
716 __checkReturn
717 HRESULT CommonGetScopeProps(
718 LPCUTF8 *pszName,
719 GUID *pMvid)
720 {
721 HRESULT hr = S_OK;
722 ModuleRec *pRec;
723 IfFailRet(GetModuleRecord(1, &pRec));
724 if (pszName != NULL)
725 {
726 IfFailRet(getNameOfModule(pRec, pszName));
727 }
728 if (pMvid != NULL)
729 {
730 IfFailRet(getMvidOfModule(pRec, pMvid));
731 }
732 return hr;
733 }
734
735 //*****************************************************************************
736 // Get name and sig of a methodDef
737 //*****************************************************************************
738 HRESULT CommonGetMethodDefProps(
739 mdMethodDef tkMethodDef,
740 LPCUTF8 *pszName,
741 DWORD *pdwFlags,
742 PCCOR_SIGNATURE *ppvSigBlob,
743 ULONG *pcbSigBlob
744 )
745 {
746
747 _ASSERTE(!IsWritable() && "IMetaModelCommonRO methods cannot be used because this importer is writable.");
748
749 HRESULT hr;
750
751 LPCUTF8 szName;
752 DWORD dwFlags;
753 PCCOR_SIGNATURE pvSigBlob;
754 ULONG cbSigBlob;
755
756 _ASSERTE(TypeFromToken(tkMethodDef) == mdtMethodDef);
757 MethodRec *pMethodRec;
758 IfFailRet(GetMethodRecord(RidFromToken(tkMethodDef), &pMethodRec));
759 IfFailRet(getNameOfMethod(pMethodRec, &szName));
760 dwFlags = getFlagsOfMethod(pMethodRec);
761 IfFailRet(getSignatureOfMethod(pMethodRec, &pvSigBlob, &cbSigBlob));
762
763 if (pszName)
764 *pszName = szName;
765 if (pdwFlags)
766 *pdwFlags = dwFlags;
767 if (ppvSigBlob)
768 *ppvSigBlob = pvSigBlob;
769 if (pcbSigBlob)
770 *pcbSigBlob = cbSigBlob;
771
772 return S_OK;
773 }
774
775 HRESULT CommonGetMemberRefProps(
776 mdMemberRef tkMemberRef,
777 mdToken *pParentToken
778 )
779 {
780 _ASSERTE(!IsWritable() && "IMetaModelCommonRO methods cannot be used because this importer is writable.");
781
782 HRESULT hr;
783
784 _ASSERTE(TypeFromToken(tkMemberRef) == mdtMemberRef);
785
786 MemberRefRec *pMemberRefRec;
787 IfFailRet(GetMemberRefRecord(RidFromToken(tkMemberRef), &pMemberRefRec));
788 if (pParentToken != NULL)
789 *pParentToken = getClassOfMemberRef(pMemberRefRec);
790
791 return S_OK;
792 }
793
794
795
796
797 __checkReturn
798 HRESULT CommonGetTypeRefProps(
799 mdTypeRef tr,
800 LPCUTF8 *pszNamespace,
801 LPCUTF8 *pszName,
802 mdToken *ptkResolution)
803 {
804 HRESULT hr = S_OK;
805 TypeRefRec *pRec;
806 IfFailRet(GetTypeRefRecord(RidFromToken(tr), &pRec));
807 if (pszNamespace != NULL)
808 {
809 IfFailRet(getNamespaceOfTypeRef(pRec, pszNamespace));
810 }
811 if (pszName != NULL)
812 {
813 IfFailRet(getNameOfTypeRef(pRec, pszName));
814 }
815 if (ptkResolution != NULL)
816 {
817 *ptkResolution = getResolutionScopeOfTypeRef(pRec);
818 }
819 return hr;
820 }
821
822 __checkReturn
823 virtual HRESULT CommonGetTypeDefProps(
824 mdTypeDef td,
825 LPCUTF8 *pszNamespace,
826 LPCUTF8 *pszName,
827 DWORD *pdwFlags,
828 mdToken *pdwExtends,
829 ULONG *pMethodList)
830 {
831 HRESULT hr = S_OK;
832 TypeDefRec *pRec;
833 IfFailRet(GetTypeDefRecord(RidFromToken(td), &pRec));
834 if (pszNamespace != NULL)
835 {
836 IfFailRet(getNamespaceOfTypeDef(pRec, pszNamespace));
837 }
838 if (pszName != NULL)
839 {
840 IfFailRet(getNameOfTypeDef(pRec, pszName));
841 }
842 if (pdwFlags != NULL)
843 {
844 *pdwFlags = getFlagsOfTypeDef(pRec);
845 }
846 if (pdwExtends != NULL)
847 {
848 *pdwExtends = getExtendsOfTypeDef(pRec);
849 }
850 if (pMethodList != NULL)
851 {
852 *pMethodList = getMethodListOfTypeDef(pRec);
853 }
854 return hr;
855 }
856
857 __checkReturn
858 virtual HRESULT CommonGetTypeSpecProps(
859 mdTypeSpec ts,
860 PCCOR_SIGNATURE *ppvSig,
861 ULONG *pcbSig)
862 {
863 HRESULT hr = S_OK;
864 TypeSpecRec *pRec;
865 IfFailRet(GetTypeSpecRecord(RidFromToken(ts), &pRec));
866 ULONG cb;
867 IfFailRet(getSignatureOfTypeSpec(pRec, ppvSig, &cb));
868 *pcbSig = cb;
869 return hr;
870 }
871
872 __checkReturn
873 virtual HRESULT CommonGetEnclosingClassOfTypeDef(
874 mdTypeDef td,
875 mdTypeDef *ptkEnclosingTypeDef)
876 {
877 _ASSERTE(ptkEnclosingTypeDef != NULL);
878
879 HRESULT hr;
880 NestedClassRec *pRec;
881 RID iRec;
882
883 IfFailRet(FindNestedClassFor(RidFromToken(td), &iRec));
884 if (iRec == 0)
885 {
886 *ptkEnclosingTypeDef = mdTypeDefNil;
887 return S_OK;
888 }
889
890 IfFailRet(GetNestedClassRecord(iRec, &pRec));
891 *ptkEnclosingTypeDef = getEnclosingClassOfNestedClass(pRec);
892 return S_OK;
893 }
894
895
896 __checkReturn
897 virtual HRESULT CommonGetAssemblyProps(
898 USHORT *pusMajorVersion,
899 USHORT *pusMinorVersion,
900 USHORT *pusBuildNumber,
901 USHORT *pusRevisionNumber,
902 DWORD *pdwFlags,
903 const void **ppbPublicKey,
904 ULONG *pcbPublicKey,
905 LPCUTF8 *pszName,
906 LPCUTF8 *pszLocale)
907 {
908 HRESULT hr = S_OK;
909 AssemblyRec *pRec;
910
911 IfFailRet(GetAssemblyRecord(1, &pRec));
912
913 if (pusMajorVersion) *pusMajorVersion = pRec->GetMajorVersion();
914 if (pusMinorVersion) *pusMinorVersion = pRec->GetMinorVersion();
915 if (pusBuildNumber) *pusBuildNumber = pRec->GetBuildNumber();
916 if (pusRevisionNumber) *pusRevisionNumber = pRec->GetRevisionNumber();
917 if (pdwFlags != NULL)
918 {
919 *pdwFlags = pRec->GetFlags();
920 }
921
922 // Turn on the afPublicKey if PublicKey blob is not empty
923 if (pdwFlags != NULL)
924 {
925 DWORD cbPublicKey;
926 const BYTE *pbPublicKey;
927 IfFailRet(getPublicKeyOfAssembly(pRec, &pbPublicKey, &cbPublicKey));
928 if (cbPublicKey)
929 *pdwFlags |= afPublicKey;
930 }
931 if (ppbPublicKey != NULL)
932 {
933 IfFailRet(getPublicKeyOfAssembly(pRec, reinterpret_cast<const BYTE **>(ppbPublicKey), pcbPublicKey));
934 }
935 if (pszName != NULL)
936 {
937 IfFailRet(getNameOfAssembly(pRec, pszName));
938 }
939 if (pszLocale != NULL)
940 {
941 IfFailRet(getLocaleOfAssembly(pRec, pszLocale));
942 }
943 return hr;
944 }
945
946 __checkReturn
947 virtual HRESULT CommonGetAssemblyRefProps(
948 mdAssemblyRef tkAssemRef,
949 USHORT *pusMajorVersion,
950 USHORT *pusMinorVersion,
951 USHORT *pusBuildNumber,
952 USHORT *pusRevisionNumber,
953 DWORD *pdwFlags,
954 const void **ppbPublicKeyOrToken,
955 ULONG *pcbPublicKeyOrToken,
956 LPCUTF8 *pszName,
957 LPCUTF8 *pszLocale,
958 const void **ppbHashValue,
959 ULONG *pcbHashValue)
960 {
961 HRESULT hr = S_OK;
962 AssemblyRefRec *pRec;
963
964 IfFailRet(GetAssemblyRefRecord(RidFromToken(tkAssemRef), &pRec));
965
966 if (pusMajorVersion) *pusMajorVersion = pRec->GetMajorVersion();
967 if (pusMinorVersion) *pusMinorVersion = pRec->GetMinorVersion();
968 if (pusBuildNumber) *pusBuildNumber = pRec->GetBuildNumber();
969 if (pusRevisionNumber) *pusRevisionNumber = pRec->GetRevisionNumber();
970 if (pdwFlags) *pdwFlags = pRec->GetFlags();
971 if (ppbPublicKeyOrToken != NULL)
972 {
973 IfFailRet(getPublicKeyOrTokenOfAssemblyRef(pRec, reinterpret_cast<const BYTE **>(ppbPublicKeyOrToken), pcbPublicKeyOrToken));
974 }
975 if (pszName != NULL)
976 {
977 IfFailRet(getNameOfAssemblyRef(pRec, pszName));
978 }
979 if (pszLocale != NULL)
980 {
981 IfFailRet(getLocaleOfAssemblyRef(pRec, pszLocale));
982 }
983 if (ppbHashValue != NULL)
984 {
985 IfFailRet(getHashValueOfAssemblyRef(pRec, reinterpret_cast<const BYTE **>(ppbHashValue), pcbHashValue));
986 }
987 return hr;
988 }
989
990 __checkReturn
991 virtual HRESULT CommonGetModuleRefProps(
992 mdModuleRef tkModuleRef,
993 LPCUTF8 *pszName)
994 {
995 HRESULT hr = S_OK;
996 ModuleRefRec *pRec;
997
998 IfFailRet(GetModuleRefRecord(RidFromToken(tkModuleRef), &pRec));
999 IfFailRet(getNameOfModuleRef(pRec, pszName));
1000 return hr;
1001 }
1002
1003 __checkReturn
1004 HRESULT CommonFindExportedType(
1005 LPCUTF8 szNamespace,
1006 LPCUTF8 szName,
1007 mdToken tkEnclosingType,
1008 mdExportedType *ptkExportedType)
1009 {
1010 HRESULT hr;
1011 ExportedTypeRec *pRec;
1012 ULONG ulCount;
1013 LPCUTF8 szTmp;
1014 mdToken tkImpl;
1015
1016 _ASSERTE(szName && ptkExportedType);
1017
1018 // Set NULL namespace to empty string.
1019 if (!szNamespace)
1020 szNamespace = "";
1021
1022 // Set output to Nil.
1023 *ptkExportedType = mdTokenNil;
1024
1025 ulCount = getCountExportedTypes();
1026 while (ulCount)
1027 {
1028 IfFailRet(GetExportedTypeRecord(ulCount--, &pRec));
1029
1030 // Handle the case of nested vs. non-nested classes.
1031 tkImpl = getImplementationOfExportedType(pRec);
1032 if (TypeFromToken(tkImpl) == mdtExportedType && !IsNilToken(tkImpl))
1033 {
1034 // Current ExportedType being looked at is a nested type, so
1035 // comparing the implementation token.
1036 if (tkImpl != tkEnclosingType)
1037 continue;
1038 }
1039 else if (TypeFromToken(tkEnclosingType) == mdtExportedType &&
1040 !IsNilToken(tkEnclosingType))
1041 {
1042 // ExportedType passed in is nested but the current ExportedType is not.
1043 continue;
1044 }
1045
1046 // Compare name and namespace.
1047 IfFailRet(getTypeNameOfExportedType(pRec, &szTmp));
1048 if (strcmp(szTmp, szName))
1049 continue;
1050 IfFailRet(getTypeNamespaceOfExportedType(pRec, &szTmp));
1051 if (!strcmp(szTmp, szNamespace))
1052 {
1053 *ptkExportedType = TokenFromRid(ulCount+1, mdtExportedType);
1054 return S_OK;
1055 }
1056 }
1057 return CLDB_E_RECORD_NOTFOUND;
1058 }
1059
1060 __checkReturn
1061 virtual HRESULT CommonGetExportedTypeProps(
1062 mdToken tkExportedType,
1063 LPCUTF8 *pszNamespace,
1064 LPCUTF8 *pszName,
1065 mdToken *ptkImpl)
1066 {
1067 HRESULT hr = S_OK;
1068 ExportedTypeRec *pRec;
1069
1070 IfFailRet(GetExportedTypeRecord(RidFromToken(tkExportedType), &pRec));
1071
1072 if (pszNamespace != NULL)
1073 {
1074 IfFailRet(getTypeNamespaceOfExportedType(pRec, pszNamespace));
1075 }
1076 if (pszName != NULL)
1077 {
1078 IfFailRet(getTypeNameOfExportedType(pRec, pszName));
1079 }
1080 if (ptkImpl) *ptkImpl = getImplementationOfExportedType(pRec);
1081 return hr;
1082 }
1083
1084 int CommonIsRo()
1085 {
1086 return static_cast<Impl*>(this)->Impl_IsRo();
1087 }
1088
1089
1090
1091 HRESULT CommonGetCustomAttributeProps(
1092 mdCustomAttribute cv, // [IN] CustomAttribute token.
1093 mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here.
1094 mdToken *ptkType, // [OUT, OPTIONAL] Put AttrType token here.
1095 const void **ppBlob, // [OUT, OPTIONAL] Put pointer to data here.
1096 ULONG *pcbSize) // [OUT, OPTIONAL] Put size of date here.
1097 {
1098 _ASSERTE(!IsWritable() && "IMetaModelCommonRO methods cannot be used because this importer is writable.");
1099
1100 HRESULT hr;
1101 _ASSERTE(TypeFromToken(cv) == mdtCustomAttribute);
1102 CustomAttributeRec *pRec; // A CustomAttribute record.
1103 const void *pBlob;
1104 ULONG cbSize;
1105 IfFailRet(GetCustomAttributeRecord(RidFromToken(cv), &pRec));
1106 if (ptkObj)
1107 *ptkObj = getParentOfCustomAttribute(pRec);
1108 if (ptkType)
1109 *ptkType = getTypeOfCustomAttribute(pRec);
1110
1111 if (!ppBlob)
1112 ppBlob = &pBlob;
1113 if (!pcbSize)
1114 pcbSize = &cbSize;
1115 IfFailRet(getValueOfCustomAttribute(pRec, (const BYTE **)ppBlob, pcbSize));
1116 return S_OK;
1117 }
1118
1119 //*****************************************************************************
1120 // Get name, parent and flags of a fieldDef
1121 //*****************************************************************************
1122 HRESULT CommonGetFieldDefProps(
1123 mdFieldDef tkFieldDef,
1124 mdTypeDef *ptkParent,
1125 LPCUTF8 *pszName,
1126 DWORD *pdwFlags
1127 )
1128 {
1129 _ASSERTE(!IsWritable() && "IMetaModelCommonRO methods cannot be used because this importer is writable.");
1130 _ASSERTE(TypeFromToken(tkFieldDef) == mdtFieldDef);
1131
1132 HRESULT hr;
1133
1134 FieldRec *pFieldRec;
1135 IfFailRet(GetFieldRecord(RidFromToken(tkFieldDef), &pFieldRec));
1136
1137 if(ptkParent)
1138 {
1139 IfFailRet(FindParentOfField(RidFromToken(tkFieldDef), (RID *) ptkParent));
1140 RidToToken(*ptkParent, mdtTypeDef);
1141 }
1142 if (pszName)
1143 IfFailRet(getNameOfField(pFieldRec, pszName));
1144 if (pdwFlags)
1145 *pdwFlags = getFlagsOfField(pFieldRec);
1146
1147 return S_OK;
1148 }
1149
1150 __checkReturn
1151 HRESULT FindParentOfMethodHelper(mdMethodDef md, mdTypeDef *ptd)
1152 {
1153 HRESULT hr;
1154 IfFailRet(FindParentOfMethod(RidFromToken(md), (RID *)ptd));
1155 RidToToken(*ptd, mdtTypeDef);
1156 return NOERROR;
1157 }
1158
1159 //*****************************************************************************
1160 // Helper function to lookup and retrieve a CustomAttribute.
1161 //*****************************************************************************
1162 __checkReturn
1163 HRESULT CompareCustomAttribute(
1164 mdToken tkObj, // [IN] Object with Custom Attribute.
1165 LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
1166 ULONG rid) // [IN] the rid of the custom attribute to compare to
1167 {
1168 CustomAttributeRec *pRec; // A CustomAttribute record.
1169 LPCUTF8 szNamespaceTmp = NULL; // Namespace of a CustomAttribute's type.
1170 LPCUTF8 szNameTmp = NULL; // Name of a CustomAttribute's type.
1171 int iLen; // Length of a component name.
1172 HRESULT hr = S_FALSE;
1173 HRESULT hrMatch = S_FALSE;
1174
1175 if (!_IsValidTokenBase(tkObj))
1176 return COR_E_BADIMAGEFORMAT;
1177
1178 // Get the row.
1179 IfFailGo(GetCustomAttributeRecord(rid, &pRec));
1180
1181 // Check the parent. In debug, always check. In retail, only when scanning.
1182 mdToken tkParent;
1183 tkParent = getParentOfCustomAttribute(pRec);
1184 if (tkObj != tkParent)
1185 {
1186 goto ErrExit;
1187 }
1188
1189 hr = CommonGetNameOfCustomAttribute(rid, &szNamespaceTmp, &szNameTmp);
1190 if (hr != S_OK)
1191 goto ErrExit;
1192
1193 iLen = -1;
1194 if (*szNamespaceTmp)
1195 {
1196 iLen = (int)strlen(szNamespaceTmp);
1197 if (strncmp(szName, szNamespaceTmp, iLen) != 0)
1198 goto ErrExit;
1199 // Namespace separator after the Namespace?
1200 if (szName[iLen] != NAMESPACE_SEPARATOR_CHAR)
1201 goto ErrExit;
1202 }
1203 // Check the type name after the separator.
1204 if (strcmp(szName+iLen+1, szNameTmp) != 0)
1205 goto ErrExit;
1206
1207 hrMatch = S_OK;
1208 ErrExit:
1209
1210 if (FAILED(hr))
1211 return hr;
1212
1213 return hrMatch;
1214 } // CompareCustomAttribute
1215
1216
1217 //*****************************************************************************
1218 // Helper function to lookup the name of a custom attribute
1219 // Note that this function can return S_FALSE to support being called
1220 // by CompareCustomAttribute. See GetTypeDefRefTokenInTypeSpec for
1221 // details on when this will happen.
1222 //*****************************************************************************
1223 __checkReturn
1224 HRESULT CommonGetNameOfCustomAttribute(
1225 ULONG rid, // [IN] the rid of the custom attribute
1226 LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute.
1227 LPCUTF8 *pszName) // [OUT] Name of Custom Attribute.
1228 {
1229 CustomAttributeRec *pRec; // A CustomAttribute record.
1230 mdToken tkTypeTmp; // Type of some CustomAttribute.
1231 RID ridTmp; // Rid of some custom value.
1232 HRESULT hr = S_FALSE;
1233
1234 // Get the row.
1235 IfFailGo(GetCustomAttributeRecord(rid, &pRec));
1236
1237 // Get the type.
1238 tkTypeTmp = getTypeOfCustomAttribute(pRec);
1239
1240 // If the record is a MemberRef or a MethodDef, we will come back here to check
1241 // the type of the parent.
1242 CheckParentType:
1243
1244 if (!_IsValidTokenBase(tkTypeTmp))
1245 return COR_E_BADIMAGEFORMAT;
1246
1247 ridTmp = RidFromToken(tkTypeTmp);
1248
1249 // Get the name of the type.
1250 switch (TypeFromToken(tkTypeTmp))
1251 {
1252 case mdtTypeRef:
1253 {
1254 TypeRefRec *pTR;
1255 IfFailGo(GetTypeRefRecord(ridTmp, &pTR));
1256 IfFailGo(getNamespaceOfTypeRef(pTR, pszNamespace));
1257 IfFailGo(getNameOfTypeRef(pTR, pszName));
1258 }
1259 break;
1260 case mdtTypeDef:
1261 {
1262 TypeDefRec *pTD;
1263 IfFailGo(GetTypeDefRecord(ridTmp, &pTD));
1264 IfFailGo(getNamespaceOfTypeDef(pTD, pszNamespace));
1265 IfFailGo(getNameOfTypeDef(pTD, pszName));
1266 }
1267 break;
1268 case mdtTypeSpec:
1269 {
1270 // If this has an encoded token, we'll take a look. If it contains
1271 // a base type, we'll just return a non-match.
1272
1273 hr = GetTypeDefRefTokenInTypeSpec(tkTypeTmp, &tkTypeTmp);
1274 IfFailGo(hr);
1275
1276 if (hr == S_OK)
1277 // Ok, tkTypeTmp should be the type token now.
1278 goto CheckParentType;
1279
1280 // This doesn't have a coded typedef or typeref.
1281 goto ErrExit;
1282 }
1283 case mdtMethodDef:
1284 {
1285 // Follow the parent.
1286 IfFailGo( FindParentOfMethodHelper(tkTypeTmp, &tkTypeTmp));
1287 goto CheckParentType;
1288 }
1289 break;
1290 case mdtMemberRef:
1291 {
1292 MemberRefRec *pMember;
1293 IfFailGo(GetMemberRefRecord(ridTmp, &pMember));
1294 // Follow the parent.
1295 tkTypeTmp = getClassOfMemberRef(pMember);
1296 goto CheckParentType;
1297 }
1298 break;
1299 case mdtString:
1300 default:
1301 if(REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AssertOnBadImageFormat, 0))
1302 _ASSERTE(!"Unexpected token type in FindCustomAttributeByName");
1303 hr = COR_E_BADIMAGEFORMAT;
1304 goto ErrExit;
1305 } // switch (TypeFromToken(tkTypeTmp))
1306
1307 hr = S_OK;
1308 ErrExit:
1309
1310 return hr;
1311 } // CommonGetNameOfCustomAttribute
1312
1313 __checkReturn
1314 HRESULT GetTypeDefRefTokenInTypeSpec(mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look
1315 mdToken *tkEnclosedToken) // [OUT] The enclosed type token
1316 {
1317 _ASSERTE(TypeFromToken(tkTypeSpec) == mdtTypeSpec);
1318 if (TypeFromToken(tkTypeSpec) != mdtTypeSpec || !_IsValidTokenBase(tkTypeSpec))
1319 return COR_E_BADIMAGEFORMAT;
1320
1321 HRESULT hr;
1322 TypeSpecRec *pTS;
1323 IfFailRet(GetTypeSpecRecord(RidFromToken(tkTypeSpec), &pTS));
1324 ULONG cbSig = 0;
1325 PCCOR_SIGNATURE pSig;
1326 PCCOR_SIGNATURE pEnd;
1327 ULONG data = 0;
1328
1329 IfFailRet(getSignatureOfTypeSpec(pTS, &pSig, &cbSig));
1330 pEnd = pSig + cbSig;
1331
1332 if (cbSig == 0)
1333 return COR_E_BADIMAGEFORMAT;
1334
1335 pSig += CorSigUncompressData(pSig, &data);
1336
1337 while (pSig < pEnd && CorIsModifierElementType((CorElementType) data))
1338 {
1339 pSig += CorSigUncompressData(pSig, &data);
1340 }
1341
1342 // See if the signature was bad
1343 if (pSig >= pEnd)
1344 return COR_E_BADIMAGEFORMAT;
1345
1346 // pSig should point to the element type now.
1347 if (data == ELEMENT_TYPE_VALUETYPE || data == ELEMENT_TYPE_CLASS)
1348 {
1349 // Get the new type token
1350 if (CorSigUncompressToken(pSig, tkEnclosedToken) == 0)
1351 return COR_E_BADIMAGEFORMAT;
1352
1353 // Ok, tkEnclosedToken should be the type token now
1354 return S_OK;
1355 }
1356
1357 // The enclosed type is a base type or an array. We don't have a token to hand out
1358 *tkEnclosedToken = mdTokenNil;
1359
1360 return S_FALSE;
1361 }
1362
1363
1364
1365 //*****************************************************************************
1366 // Given a scope, return the number of tokens in a given table
1367 //*****************************************************************************
1368 ULONG CommonGetRowCount( // return hresult
1369 DWORD tkKind) // [IN] pass in the kind of token.
1370 {
1371 _ASSERTE(!IsWritable() && "IMetaModelCommonRO methods cannot be used because this importer is writable.");
1372
1373 ULONG ulCount = 0;
1374
1375 switch (tkKind)
1376 {
1377 case mdtTypeDef:
1378 ulCount = getCountTypeDefs();
1379 break;
1380 case mdtTypeRef:
1381 ulCount = getCountTypeRefs();
1382 break;
1383 case mdtMethodDef:
1384 ulCount = getCountMethods();
1385 break;
1386 case mdtFieldDef:
1387 ulCount = getCountFields();
1388 break;
1389 case mdtMemberRef:
1390 ulCount = getCountMemberRefs();
1391 break;
1392 case mdtInterfaceImpl:
1393 ulCount = getCountInterfaceImpls();
1394 break;
1395 case mdtParamDef:
1396 ulCount = getCountParams();
1397 break;
1398 case mdtFile:
1399 ulCount = getCountFiles();
1400 break;
1401 case mdtAssemblyRef:
1402 ulCount = getCountAssemblyRefs();
1403 break;
1404 case mdtAssembly:
1405 ulCount = getCountAssemblys();
1406 break;
1407 case mdtCustomAttribute:
1408 ulCount = getCountCustomAttributes();
1409 break;
1410 case mdtModule:
1411 ulCount = getCountModules();
1412 break;
1413 case mdtPermission:
1414 ulCount = getCountDeclSecuritys();
1415 break;
1416 case mdtSignature:
1417 ulCount = getCountStandAloneSigs();
1418 break;
1419 case mdtEvent:
1420 ulCount = getCountEvents();
1421 break;
1422 case mdtProperty:
1423 ulCount = getCountPropertys();
1424 break;
1425 case mdtModuleRef:
1426 ulCount = getCountModuleRefs();
1427 break;
1428 case mdtTypeSpec:
1429 ulCount = getCountTypeSpecs();
1430 break;
1431 case mdtExportedType:
1432 ulCount = getCountExportedTypes();
1433 break;
1434 case mdtManifestResource:
1435 ulCount = getCountManifestResources();
1436 break;
1437 case mdtGenericParam:
1438 ulCount = getCountGenericParams();
1439 break;
1440 case mdtMethodSpec:
1441 ulCount = getCountMethodSpecs();
1442 break;
1443 default:
1444 Debug_ReportError("Invalid token kind (table)");
1445 ulCount = 0;
1446 break;
1447 }
1448 return ulCount;
1449 } // ULONG CommonGetRowCount()
1450
1451
1452
1453 //*****************************************************************************
1454 // Locate methodimpl token range for a given typeDef
1455 //*****************************************************************************
1456 HRESULT CommonGetMethodImpls(
1457 mdTypeDef tkTypeDef, // [IN] typeDef to scope search
1458 mdToken *ptkMethodImplFirst, // [OUT] returns first methodImpl token
1459 ULONG *pMethodImplCount // [OUT] returns # of methodImpl tokens scoped to type
1460 )
1461 {
1462 _ASSERTE(!IsWritable() && "IMetaModelCommonRO methods cannot be used because this importer is writable.");
1463
1464 _ASSERTE(TypeFromToken(tkTypeDef) == mdtTypeDef);
1465 _ASSERTE(ptkMethodImplFirst != NULL);
1466 _ASSERTE(pMethodImplCount != NULL);
1467
1468 HRESULT hr;
1469
1470 RID ridEnd;
1471 RID ridStart;
1472 IfFailGo(getMethodImplsForClass(RidFromToken(tkTypeDef), &ridEnd, &ridStart));
1473 *pMethodImplCount = ridEnd - ridStart;
1474 if (*pMethodImplCount)
1475 {
1476 *ptkMethodImplFirst = TokenFromRid(TBL_MethodImpl << 24, ridStart);
1477 }
1478 hr = S_OK;
1479
1480 ErrExit:
1481 return hr;
1482 }
1483
1484 //*****************************************************************************
1485 // Extract row info for methodImpl
1486 //*****************************************************************************
1487 HRESULT CommonGetMethodImplProps(
1488 mdToken tkMethodImpl, // [IN] methodImpl
1489 mdToken *pBody, // [OUT] returns body token
1490 mdToken *pDecl // [OUT] returns decl token
1491 )
1492 {
1493 _ASSERTE(!IsWritable() && "IMetaModelCommonRO methods cannot be used because this importer is writable.");
1494
1495 HRESULT hr;
1496 _ASSERTE(TypeFromToken(tkMethodImpl) == (TBL_MethodImpl << 24));
1497 _ASSERTE(pBody != NULL);
1498 _ASSERTE(pDecl != NULL);
1499 MethodImplRec *pRec;
1500 IfFailGo(GetMethodImplRecord(RidFromToken(tkMethodImpl), &pRec));
1501 *pBody = getMethodBodyOfMethodImpl(pRec);
1502 *pDecl = getMethodDeclarationOfMethodImpl(pRec);
1503 hr = S_OK;
1504 ErrExit:
1505 return hr;
1506 }
1507
1508 // IMetaModelCommonRO interface end
1509
1510
1511
1512
1513public:
1514// friend class CLiteWeightStgdb;
1515
1516 __checkReturn
1517 virtual HRESULT vGetRow(UINT32 nTableIndex, UINT32 nRowIndex, void **ppRow)
1518 {
1519 return getRow(nTableIndex, nRowIndex, ppRow);
1520 }
1521
1522public:
1523
1524 //*************************************************************************
1525 // This group of functions are table-level (one function per table). Functions like
1526 // getting a count of rows.
1527
1528 // Functions to get the count of rows in a table. Functions like:
1529 // ULONG getCountXyzs() { return m_Schema.m_cRecs[TBL_Xyz];}
1530#undef MiniMdTable
1531#define MiniMdTable(tbl) ULONG getCount##tbl##s() { return _TBLCNT(tbl); }
1532 MiniMdTables();
1533 // macro misspells some names.
1534 ULONG getCountProperties() {return getCountPropertys();}
1535 ULONG getCountMethodSemantics() {return getCountMethodSemanticss();}
1536
1537 // Functions for getting a row by rid. Look like:
1538 // HRESULT GetXyzRecord(RID rid, XyzRec **ppRecord) { return m_Tables[TBL_Xyz].GetRecord(rid, ppRecord); }
1539 // e.g.:
1540 // HRESULT GetMethodRecord(RID rid, MethodRec **ppRecord) { return m_Tables[TBL_Method].GetRecord(rid, ppRecord); }
1541 #undef MiniMdTable
1542#define MiniMdTable(tbl) __checkReturn HRESULT Get##tbl##Record(RID rid, tbl##Rec **ppRecord) { \
1543 return getRow(TBL_##tbl, rid, reinterpret_cast<void **>(ppRecord)); }
1544 MiniMdTables();
1545
1546 //*************************************************************************
1547 // These are specialized searching functions. Mostly generic (ie, find
1548 // a custom value for any object).
1549
1550 // Functions to search for a record relating to another record.
1551 // Return RID to Constant table.
1552 __checkReturn
1553 HRESULT FindConstantFor(RID rid, mdToken typ, RID *pFoundRid)
1554 { return doSearchTable(TBL_Constant, _COLPAIR(Constant,Parent), encodeToken(rid,typ,mdtHasConstant,lengthof(mdtHasConstant)), pFoundRid); }
1555
1556 // Return RID to FieldMarshal table.
1557 __checkReturn
1558 HRESULT FindFieldMarshalFor(RID rid, mdToken typ, RID *pFoundRid)
1559 { return doSearchTable(TBL_FieldMarshal, _COLPAIR(FieldMarshal,Parent), encodeToken(rid,typ,mdtHasFieldMarshal,lengthof(mdtHasFieldMarshal)), pFoundRid); }
1560
1561 // Return RID to ClassLayout table, given the rid to a TypeDef.
1562 __checkReturn
1563 HRESULT FindClassLayoutFor(RID rid, RID *pFoundRid)
1564 { return doSearchTable(TBL_ClassLayout, _COLPAIR(ClassLayout,Parent), RidFromToken(rid), pFoundRid); }
1565
1566 // given a rid to the Event table, find an entry in EventMap table that contains the back pointer
1567 // to its typedef parent
1568 __checkReturn
1569 HRESULT FindEventMapParentOfEvent(RID rid, RID *pFoundRid)
1570 {
1571 return vSearchTableNotGreater(TBL_EventMap, _COLDEF(EventMap,EventList), rid, pFoundRid);
1572 }
1573 // return the parent eventmap rid given a event rid
1574 __checkReturn
1575 HRESULT FindParentOfEvent(RID rid, RID *pFoundRid)
1576 {
1577 return vSearchTableNotGreater(TBL_EventMap, _COLDEF(EventMap,EventList), rid, pFoundRid);
1578 }
1579
1580 // given a rid to the Event table, find an entry in EventMap table that contains the back pointer
1581 // to its typedef parent
1582 __checkReturn
1583 HRESULT FindPropertyMapParentOfProperty(RID rid, RID *pFoundRid)
1584 {
1585 return vSearchTableNotGreater(TBL_PropertyMap, _COLDEF(PropertyMap,PropertyList), rid, pFoundRid);
1586 }
1587 // return the parent propertymap rid given a property rid
1588 __checkReturn
1589 HRESULT FindParentOfProperty(RID rid, RID *pFoundRid)
1590 {
1591 return vSearchTableNotGreater(TBL_PropertyMap, _COLDEF(PropertyMap,PropertyList), rid, pFoundRid);
1592 }
1593
1594 // Return RID to MethodSemantics table, given the rid to a MethodDef.
1595 __checkReturn
1596 HRESULT FindMethodSemanticsFor(RID rid, RID *pFoundRid)
1597 { return doSearchTable(TBL_MethodSemantics, _COLPAIR(MethodSemantics,Method), RidFromToken(rid), pFoundRid); }
1598
1599 // return the parent typedef rid given a field def rid
1600 __checkReturn
1601 HRESULT FindParentOfField(RID rid, RID *pFoundRid)
1602 {
1603 return vSearchTableNotGreater(TBL_TypeDef, _COLDEF(TypeDef,FieldList), rid, pFoundRid);
1604 }
1605
1606 // return the parent typedef rid given a method def rid
1607 __checkReturn
1608 HRESULT FindParentOfMethod(RID rid, RID *pFoundRid)
1609 {
1610 return vSearchTableNotGreater(TBL_TypeDef, _COLDEF(TypeDef,MethodList), rid, pFoundRid);
1611 }
1612
1613 __checkReturn
1614 HRESULT FindParentOfParam(RID rid, RID *pFoundRid)
1615 {
1616 return vSearchTableNotGreater(TBL_Method, _COLDEF(Method,ParamList), rid, pFoundRid);
1617 }
1618
1619 // Find a FieldLayout record given the corresponding Field.
1620 __checkReturn
1621 HRESULT FindFieldLayoutFor(RID rid, RID *pFoundRid)
1622 { return doSearchTable(TBL_FieldLayout, _COLPAIR(FieldLayout, Field), rid, pFoundRid); }
1623
1624 // Return RID to Constant table.
1625 __checkReturn
1626 HRESULT FindImplMapFor(RID rid, mdToken typ, RID *pFoundRid)
1627 { return doSearchTable(TBL_ImplMap, _COLPAIR(ImplMap,MemberForwarded), encodeToken(rid,typ,mdtMemberForwarded,lengthof(mdtMemberForwarded)), pFoundRid); }
1628
1629 // Return RID to FieldRVA table.
1630 __checkReturn
1631 HRESULT FindFieldRVAFor(RID rid, RID *pFoundRid)
1632 { return doSearchTable(TBL_FieldRVA, _COLPAIR(FieldRVA, Field), rid, pFoundRid); }
1633
1634 // Find a NestedClass record given the corresponding Field.
1635 __checkReturn
1636 HRESULT FindNestedClassFor(RID rid, RID *pFoundRid)
1637 { return doSearchTable(TBL_NestedClass, _COLPAIR(NestedClass, NestedClass), rid, pFoundRid); }
1638
1639 //*************************************************************************
1640 // These are table-specific functions.
1641
1642 // ModuleRec
1643 _GETSTR(Module,Name);
1644 __checkReturn HRESULT _GETGUID(Module,Mvid);
1645 __checkReturn HRESULT _GETGUID(Module,EncId);
1646 __checkReturn HRESULT _GETGUID(Module,EncBaseId);
1647
1648 // TypeRefRec
1649 mdToken _GETCDTKN(TypeRef, ResolutionScope, mdtResolutionScope);
1650 _GETSTR(TypeRef, Name);
1651 _GETSTR(TypeRef, Namespace);
1652
1653 // TypeDefRec
1654 ULONG _GETFLD(TypeDef,Flags); // USHORT getFlagsOfTypeDef(TypeDefRec *pRec);
1655 _GETSTR(TypeDef,Name);
1656 _GETSTR(TypeDef,Namespace);
1657
1658 _GETLIST(TypeDef,FieldList,Field); // RID getFieldListOfTypeDef(TypeDefRec *pRec);
1659 _GETLIST(TypeDef,MethodList,Method); // RID getMethodListOfTypeDef(TypeDefRec *pRec);
1660 mdToken _GETCDTKN(TypeDef,Extends,mdtTypeDefOrRef); // mdToken getExtendsOfTypeDef(TypeDefRec *pRec);
1661
1662 __checkReturn
1663 HRESULT getGenericParamsForTypeDef(RID rid, RID *pEnd, RID *pFoundRid)
1664 {
1665 return SearchTableForMultipleRows(TBL_GenericParam,
1666 _COLDEF(GenericParam,Owner),
1667 encodeToken(rid, mdtTypeDef, mdtTypeOrMethodDef, lengthof(mdtTypeOrMethodDef)),
1668 pEnd,
1669 pFoundRid);
1670 }
1671 __checkReturn
1672 HRESULT getGenericParamsForMethodDef(RID rid, RID *pEnd, RID *pFoundRid)
1673 {
1674 return SearchTableForMultipleRows(TBL_GenericParam,
1675 _COLDEF(GenericParam,Owner),
1676 encodeToken(rid, mdtMethodDef, mdtTypeOrMethodDef, lengthof(mdtTypeOrMethodDef)),
1677 pEnd,
1678 pFoundRid);
1679 }
1680 __checkReturn
1681 HRESULT getMethodSpecsForMethodDef(RID rid, RID *pEnd, RID *pFoundRid)
1682 {
1683 return SearchTableForMultipleRows(TBL_MethodSpec,
1684 _COLDEF(MethodSpec,Method),
1685 encodeToken(rid, mdtMethodDef, mdtMethodDefOrRef, lengthof(mdtMethodDefOrRef)),
1686 pEnd,
1687 pFoundRid);
1688 }
1689 __checkReturn
1690 HRESULT getMethodSpecsForMemberRef(RID rid, RID *pEnd, RID *pFoundRid)
1691 {
1692 return SearchTableForMultipleRows(TBL_MethodSpec,
1693 _COLDEF(MethodSpec,Method),
1694 encodeToken(rid, mdtMemberRef, mdtMethodDefOrRef, lengthof(mdtMethodDefOrRef)),
1695 pEnd,
1696 pFoundRid);
1697 }
1698 __checkReturn
1699 HRESULT getInterfaceImplsForTypeDef(RID rid, RID *pEnd, RID *pFoundRid)
1700 {
1701 return SearchTableForMultipleRows(TBL_InterfaceImpl,
1702 _COLDEF(InterfaceImpl,Class),
1703 rid,
1704 pEnd,
1705 pFoundRid);
1706 }
1707
1708 // FieldPtr
1709 ULONG _GETRID(FieldPtr,Field);
1710
1711 // FieldRec
1712 USHORT _GETFLD(Field,Flags); // USHORT getFlagsOfField(FieldRec *pRec);
1713 _GETSTR(Field,Name); // HRESULT getNameOfField(FieldRec *pRec, LPCUTF8 *pszString);
1714 _GETSIGBLOB(Field,Signature); // HRESULT getSignatureOfField(FieldRec *pRec, PCCOR_SIGNATURE *ppbData, ULONG *pcbSize);
1715
1716 // MethodPtr
1717 ULONG _GETRID(MethodPtr,Method);
1718
1719 // MethodRec
1720 ULONG _GETFLD(Method,RVA);
1721 USHORT _GETFLD(Method,ImplFlags);
1722 USHORT _GETFLD(Method,Flags);
1723 _GETSTR(Method,Name); // HRESULT getNameOfMethod(MethodRec *pRec, LPCUTF8 *pszString);
1724 _GETSIGBLOB(Method,Signature); // HRESULT getSignatureOfMethod(MethodRec *pRec, PCCOR_SIGNATURE *ppbData, ULONG *pcbSize);
1725 _GETLIST(Method,ParamList,Param);
1726
1727 // ParamPtr
1728 ULONG _GETRID(ParamPtr,Param);
1729
1730 // ParamRec
1731 USHORT _GETFLD(Param,Flags);
1732 USHORT _GETFLD(Param,Sequence);
1733 _GETSTR(Param,Name);
1734
1735 // InterfaceImplRec
1736 mdToken _GETTKN(InterfaceImpl,Class,mdtTypeDef);
1737 mdToken _GETCDTKN(InterfaceImpl,Interface,mdtTypeDefOrRef);
1738
1739 // MemberRefRec
1740 mdToken _GETCDTKN(MemberRef,Class,mdtMemberRefParent);
1741 _GETSTR(MemberRef,Name);
1742 _GETSIGBLOB(MemberRef,Signature); // HRESULT getSignatureOfMemberRef(MemberRefRec *pRec, PCCOR_SIGNATURE *ppbData, ULONG *pcbSize);
1743
1744 // ConstantRec
1745 BYTE _GETFLD(Constant,Type);
1746 mdToken _GETCDTKN(Constant,Parent,mdtHasConstant);
1747 _GETBLOB(Constant,Value);
1748
1749 // CustomAttributeRec
1750 __checkReturn
1751 HRESULT getCustomAttributeForToken(mdToken tk, RID *pEnd, RID *pFoundRid)
1752 {
1753 return SearchTableForMultipleRows(TBL_CustomAttribute,
1754 _COLDEF(CustomAttribute,Parent),
1755 encodeToken(RidFromToken(tk), TypeFromToken(tk), mdtHasCustomAttribute, lengthof(mdtHasCustomAttribute)),
1756 pEnd,
1757 pFoundRid);
1758 }
1759
1760 mdToken _GETCDTKN(CustomAttribute,Parent,mdtHasCustomAttribute);
1761 mdToken _GETCDTKN(CustomAttribute,Type,mdtCustomAttributeType);
1762 _GETBLOB(CustomAttribute,Value);
1763
1764 // FieldMarshalRec
1765 mdToken _GETCDTKN(FieldMarshal,Parent,mdtHasFieldMarshal);
1766 _GETSIGBLOB(FieldMarshal,NativeType);
1767
1768 // DeclSecurityRec
1769 __checkReturn
1770 HRESULT getDeclSecurityForToken(mdToken tk, RID *pEnd, RID *pFoundRid)
1771 {
1772 return SearchTableForMultipleRows(TBL_DeclSecurity,
1773 _COLDEF(DeclSecurity,Parent),
1774 encodeToken(RidFromToken(tk), TypeFromToken(tk), mdtHasDeclSecurity, lengthof(mdtHasDeclSecurity)),
1775 pEnd,
1776 pFoundRid);
1777 }
1778
1779 short _GETFLD(DeclSecurity,Action);
1780 mdToken _GETCDTKN(DeclSecurity,Parent,mdtHasDeclSecurity);
1781 _GETBLOB(DeclSecurity,PermissionSet);
1782
1783 // ClassLayoutRec
1784 USHORT _GETFLD(ClassLayout,PackingSize);
1785 ULONG _GETFLD(ClassLayout,ClassSize);
1786 ULONG _GETTKN(ClassLayout,Parent, mdtTypeDef);
1787
1788 // FieldLayout
1789 ULONG _GETFLD(FieldLayout,OffSet);
1790 ULONG _GETTKN(FieldLayout, Field, mdtFieldDef);
1791
1792 // Event map.
1793 _GETLIST(EventMap,EventList,Event);
1794 ULONG _GETRID(EventMap, Parent);
1795
1796 // EventPtr
1797 ULONG _GETRID(EventPtr, Event);
1798
1799 // Event.
1800 USHORT _GETFLD(Event,EventFlags);
1801 _GETSTR(Event,Name);
1802 mdToken _GETCDTKN(Event,EventType,mdtTypeDefOrRef);
1803
1804 // Property map.
1805 _GETLIST(PropertyMap,PropertyList,Property);
1806 ULONG _GETRID(PropertyMap, Parent);
1807
1808 // PropertyPtr
1809 ULONG _GETRID(PropertyPtr, Property);
1810
1811 // Property.
1812 USHORT _GETFLD(Property,PropFlags);
1813 _GETSTR(Property,Name);
1814 _GETSIGBLOB(Property,Type);
1815
1816 // MethodSemantics.
1817 // Given an event or a property token, return the beginning/ending
1818 // associates.
1819 //
1820 __checkReturn
1821 HRESULT getAssociatesForToken(mdToken tk, RID *pEnd, RID *pFoundRid)
1822 {
1823 return SearchTableForMultipleRows(TBL_MethodSemantics,
1824 _COLDEF(MethodSemantics,Association),
1825 encodeToken(RidFromToken(tk), TypeFromToken(tk), mdtHasSemantic, lengthof(mdtHasSemantic)),
1826 pEnd,
1827 pFoundRid);
1828 }
1829
1830 USHORT _GETFLD(MethodSemantics,Semantic);
1831 mdToken _GETTKN(MethodSemantics,Method,mdtMethodDef);
1832 mdToken _GETCDTKN(MethodSemantics,Association,mdtHasSemantic);
1833
1834 // MethodImpl
1835 // Given a class token, return the beginning/ending MethodImpls.
1836 //
1837 __checkReturn
1838 HRESULT getMethodImplsForClass(RID rid, RID *pEnd, RID *pFoundRid)
1839 {
1840 return SearchTableForMultipleRows(TBL_MethodImpl,
1841 _COLDEF(MethodImpl, Class),
1842 rid,
1843 pEnd,
1844 pFoundRid);
1845 }
1846
1847 mdToken _GETTKN(MethodImpl,Class,mdtTypeDef);
1848 mdToken _GETCDTKN(MethodImpl,MethodBody, mdtMethodDefOrRef);
1849 mdToken _GETCDTKN(MethodImpl, MethodDeclaration, mdtMethodDefOrRef);
1850
1851 // StandAloneSigRec
1852 _GETSIGBLOB(StandAloneSig,Signature); // HRESULT getSignatureOfStandAloneSig(StandAloneSigRec *pRec, PCCOR_SIGNATURE *ppbData, ULONG *pcbSize);
1853
1854 // TypeSpecRec
1855 // const BYTE* getSignatureOfTypeSpec(TypeSpecRec *pRec, ULONG *pcb);
1856 _GETSIGBLOB(TypeSpec,Signature);
1857
1858 // ModuleRef
1859 _GETSTR(ModuleRef,Name);
1860
1861 // ENCLog
1862 ULONG _GETFLD(ENCLog, FuncCode); // ULONG getFuncCodeOfENCLog(ENCLogRec *pRec);
1863
1864 // ImplMap
1865 USHORT _GETFLD(ImplMap, MappingFlags); // USHORT getMappingFlagsOfImplMap(ImplMapRec *pRec);
1866 mdToken _GETCDTKN(ImplMap, MemberForwarded, mdtMemberForwarded); // mdToken getMemberForwardedOfImplMap(ImplMapRec *pRec);
1867 _GETSTR(ImplMap, ImportName); // HRESULT getImportNameOfImplMap(ImplMapRec *pRec, LPCUTF8 *pszString);
1868 mdToken _GETTKN(ImplMap, ImportScope, mdtModuleRef); // mdToken getImportScopeOfImplMap(ImplMapRec *pRec);
1869
1870 // FieldRVA
1871 ULONG _GETFLD(FieldRVA, RVA); // ULONG getRVAOfFieldRVA(FieldRVARec *pRec);
1872 mdToken _GETTKN(FieldRVA, Field, mdtFieldDef); // mdToken getFieldOfFieldRVA(FieldRVARec *pRec);
1873
1874 // Assembly
1875 ULONG _GETFLD(Assembly, HashAlgId);
1876 USHORT _GETFLD(Assembly, MajorVersion);
1877 USHORT _GETFLD(Assembly, MinorVersion);
1878 USHORT _GETFLD(Assembly, BuildNumber);
1879 USHORT _GETFLD(Assembly, RevisionNumber);
1880 ULONG _GETFLD(Assembly, Flags);
1881 _GETBLOB(Assembly, PublicKey);
1882 _GETSTR(Assembly, Name);
1883 _GETSTR(Assembly, Locale);
1884
1885 // AssemblyRef
1886 USHORT _GETFLD(AssemblyRef, MajorVersion);
1887 USHORT _GETFLD(AssemblyRef, MinorVersion);
1888 USHORT _GETFLD(AssemblyRef, BuildNumber);
1889 USHORT _GETFLD(AssemblyRef, RevisionNumber);
1890 ULONG _GETFLD(AssemblyRef, Flags);
1891 _GETBLOB(AssemblyRef, PublicKeyOrToken);
1892 _GETSTR(AssemblyRef, Name);
1893 _GETSTR(AssemblyRef, Locale);
1894 _GETBLOB(AssemblyRef, HashValue);
1895
1896 // File
1897 ULONG _GETFLD(File, Flags);
1898 _GETSTR(File, Name);
1899 _GETBLOB(File, HashValue);
1900
1901 // ExportedType
1902 ULONG _GETFLD(ExportedType, Flags);
1903 ULONG _GETFLD(ExportedType, TypeDefId);
1904 _GETSTR(ExportedType, TypeName);
1905 _GETSTR(ExportedType, TypeNamespace);
1906 mdToken _GETCDTKN(ExportedType, Implementation, mdtImplementation);
1907
1908 // ManifestResource
1909 ULONG _GETFLD(ManifestResource, Offset);
1910 ULONG _GETFLD(ManifestResource, Flags);
1911 _GETSTR(ManifestResource, Name);
1912 mdToken _GETCDTKN(ManifestResource, Implementation, mdtImplementation);
1913
1914 // NestedClass
1915 mdToken _GETTKN(NestedClass, NestedClass, mdtTypeDef);
1916 mdToken _GETTKN(NestedClass, EnclosingClass, mdtTypeDef);
1917
1918 int GetSizeOfMethodNameColumn()
1919 {
1920 return _COLDEF(Method,Name).m_cbColumn;
1921 }
1922
1923 // GenericParRec
1924 USHORT _GETFLD(GenericParam,Number);
1925 USHORT _GETFLD(GenericParam,Flags);
1926 mdToken _GETCDTKN(GenericParam,Owner,mdtTypeOrMethodDef);
1927 _GETSTR(GenericParam,Name);
1928
1929 __checkReturn
1930 HRESULT getGenericParamConstraintsForGenericParam(RID rid, RID *pEnd, RID *pFoundRid)
1931 {
1932 return SearchTableForMultipleRows(TBL_GenericParamConstraint,
1933 _COLDEF(GenericParamConstraint,Owner),
1934 rid,
1935 pEnd,
1936 pFoundRid);
1937 }
1938
1939 // MethodSpecRec
1940 mdToken _GETCDTKN(MethodSpec,Method,mdtMethodDefOrRef);
1941 _GETSIGBLOB(MethodSpec,Instantiation);
1942
1943 //GenericParamConstraintRec
1944 mdToken _GETTKN(GenericParamConstraint,Owner,mdtGenericParam);
1945 mdToken _GETCDTKN(GenericParamConstraint,Constraint,mdtTypeDefOrRef);
1946
1947 BOOL SupportsGenerics()
1948 {
1949 // Only 2.0 of the metadata (and 1.1) support generics
1950 return (m_Schema.m_major >= METAMODEL_MAJOR_VER_V2_0 ||
1951 (m_Schema.m_major == METAMODEL_MAJOR_VER_B1 && m_Schema.m_minor == METAMODEL_MINOR_VER_B1));
1952 }// SupportGenerics
1953
1954 protected:
1955 //*****************************************************************************
1956 // Helper: determine if a token is valid or not
1957 //*****************************************************************************
1958 BOOL _IsValidTokenBase(
1959 mdToken tk)
1960 {
1961 BOOL bRet = FALSE;
1962 RID rid = RidFromToken(tk);
1963
1964 if (rid != 0)
1965 {
1966 switch (TypeFromToken(tk))
1967 {
1968 case mdtModule:
1969 // can have only one module record
1970 bRet = (rid <= getCountModules());
1971 break;
1972 case mdtTypeRef:
1973 bRet = (rid <= getCountTypeRefs());
1974 break;
1975 case mdtTypeDef:
1976 bRet = (rid <= getCountTypeDefs());
1977 break;
1978 case mdtFieldDef:
1979 bRet = (rid <= getCountFields());
1980 break;
1981 case mdtMethodDef:
1982 bRet = (rid <= getCountMethods());
1983 break;
1984 case mdtParamDef:
1985 bRet = (rid <= getCountParams());
1986 break;
1987 case mdtInterfaceImpl:
1988 bRet = (rid <= getCountInterfaceImpls());
1989 break;
1990 case mdtMemberRef:
1991 bRet = (rid <= getCountMemberRefs());
1992 break;
1993 case mdtCustomAttribute:
1994 bRet = (rid <= getCountCustomAttributes());
1995 break;
1996 case mdtPermission:
1997 bRet = (rid <= getCountDeclSecuritys());
1998 break;
1999 case mdtSignature:
2000 bRet = (rid <= getCountStandAloneSigs());
2001 break;
2002 case mdtEvent:
2003 bRet = (rid <= getCountEvents());
2004 break;
2005 case mdtProperty:
2006 bRet = (rid <= getCountPropertys());
2007 break;
2008 case mdtModuleRef:
2009 bRet = (rid <= getCountModuleRefs());
2010 break;
2011 case mdtTypeSpec:
2012 bRet = (rid <= getCountTypeSpecs());
2013 break;
2014 case mdtAssembly:
2015 bRet = (rid <= getCountAssemblys());
2016 break;
2017 case mdtAssemblyRef:
2018 bRet = (rid <= getCountAssemblyRefs());
2019 break;
2020 case mdtFile:
2021 bRet = (rid <= getCountFiles());
2022 break;
2023 case mdtExportedType:
2024 bRet = (rid <= getCountExportedTypes());
2025 break;
2026 case mdtManifestResource:
2027 bRet = (rid <= getCountManifestResources());
2028 break;
2029 case mdtGenericParam:
2030 bRet = (rid <= getCountGenericParams());
2031 break;
2032 case mdtGenericParamConstraint:
2033 bRet = (rid <= getCountGenericParamConstraints());
2034 break;
2035 case mdtMethodSpec:
2036 bRet = (rid <= getCountMethodSpecs());
2037 break;
2038 default:
2039 _ASSERTE(!bRet);
2040 Debug_ReportError("Unknown token kind!");
2041 }
2042 }
2043 return bRet;
2044 } // _IsValidToken
2045
2046#ifdef FEATURE_METADATA_RELEASE_MEMORY_ON_REOPEN
2047 bool IsSafeToDelete()
2048 {
2049 return m_isSafeToDelete;
2050 }
2051
2052 FORCEINLINE void MarkUnsafeToDelete() { m_isSafeToDelete = false; }
2053
2054 bool m_isSafeToDelete; // This starts out true, but gets set to FALSE if we detect
2055 // a MiniMd API call that might have given out an internal pointer.
2056#endif
2057
2058}; //class CMiniMdTemplate<Impl>
2059
2060
2061
2062#undef SETP
2063#undef _GETCDTKN
2064#undef _GETTKN
2065#undef _GETRID
2066#undef _GETBLOB
2067#undef _GETGUID
2068#undef _GETSTR
2069#undef SCHEMA
2070
2071#endif // _METAMODEL_H_
2072// eof ------------------------------------------------------------------------
2073