| 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 | |
| 45 | typedef 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 | |
| 56 | struct HENUMInternal; |
| 57 | extern const CCodedTokenDef g_CodedTokens[CDTKN_COUNT]; |
| 58 | extern const CMiniTableDefEx g_Tables[TBL_COUNT]; // The table definitions. |
| 59 | |
| 60 | struct TblCol |
| 61 | { |
| 62 | ULONG m_ixtbl; // Table ID. |
| 63 | ULONG m_ixcol; // Column ID. |
| 64 | }; |
| 65 | extern 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) |
| 69 | class IMetaModelCommon |
| 70 | { |
| 71 | public: |
| 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. |
| 184 | class IMetaModelCommonRO : public IMetaModelCommon |
| 185 | { |
| 186 | public: |
| 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 | |
| 238 | class CMiniMdSchemaBase |
| 239 | { |
| 240 | public: |
| 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 | = 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 | |
| 283 | private: |
| 284 | FORCEINLINE unsigned __int64 BIT(ULONG ixBit) |
| 285 | { _ASSERTE(ixBit < (sizeof(__int64)*CHAR_BIT)); |
| 286 | return UI64(1) << ixBit; } |
| 287 | |
| 288 | }; |
| 289 | |
| 290 | class CMiniMdSchema : public CMiniMdSchemaBase |
| 291 | { |
| 292 | public: |
| 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 ; // 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 | //***************************************************************************** |
| 411 | class CMiniMdBase : public IMetaModelCommonRO |
| 412 | { |
| 413 | |
| 414 | friend class VerifyLayoutsMD; // verifies class layout doesn't accidentally change |
| 415 | |
| 416 | public: |
| 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 | |
| 601 | public: |
| 602 | virtual BOOL IsWritable() = 0; |
| 603 | |
| 604 | |
| 605 | protected: |
| 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 , BOOL fUsePointers); |
| 630 | __checkReturn |
| 631 | HRESULT SchemaPopulate2(ULONG *pcbTables, int =false); |
| 632 | const CMiniTableDef* GetTableDefTemplate(int ixTbl); |
| 633 | __checkReturn |
| 634 | HRESULT SetNewColumnDefinition(CMiniTableDef *pTable, CMiniColDef* pCols, DWORD ixTbl); |
| 635 | |
| 636 | private: |
| 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 | //***************************************************************************** |
| 658 | template <class Impl> class CMiniMdTemplate : public CMiniMdBase |
| 659 | { |
| 660 | #ifdef FEATURE_METADATA_RELEASE_MEMORY_ON_REOPEN |
| 661 | protected: |
| 662 | CMiniMdTemplate() : m_isSafeToDelete(TRUE) { } |
| 663 | #endif |
| 664 | |
| 665 | // Primitives -- these must be implemented in the Impl class. |
| 666 | public: |
| 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 | |
| 1513 | public: |
| 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 | |
| 1522 | public: |
| 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 | |