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// File: MDInternalRO.CPP
6//
7
8// Notes:
9//
10//
11// ===========================================================================
12#include "stdafx.h"
13#include "mdinternalro.h"
14#include "metamodelro.h"
15#include "liteweightstgdb.h"
16#include "corhlpr.h"
17#include "../compiler/regmeta.h"
18#include "caparser.h"
19
20#ifdef FEATURE_METADATA_INTERNAL_APIS
21
22__checkReturn
23HRESULT _FillMDDefaultValue(
24 BYTE bType,
25 void const *pValue,
26 ULONG cbValue,
27 MDDefaultValue *pMDDefaultValue);
28
29#ifndef DACCESS_COMPILE
30__checkReturn
31HRESULT TranslateSigHelper( // S_OK or error.
32 IMDInternalImport *pImport, // [IN] import scope.
33 IMDInternalImport *pAssemImport, // [IN] import assembly scope.
34 const void *pbHashValue, // [IN] hash value for the import assembly.
35 ULONG cbHashValue, // [IN] count of bytes in the hash value.
36 PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope
37 ULONG cbSigBlob, // [IN] count of bytes of signature
38 IMetaDataAssemblyEmit *pAssemEmit, // [IN] assembly emit scope.
39 IMetaDataEmit *emit, // [IN] emit interface
40 CQuickBytes *pqkSigEmit, // [OUT] buffer to hold translated signature
41 ULONG *pcbSig); // [OUT] count of bytes in the translated signature
42#endif //!DACCESS_COMPILE
43
44__checkReturn
45HRESULT GetInternalWithRWFormat(
46 LPVOID pData,
47 ULONG cbData,
48 DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC
49 REFIID riid, // [in] The interface desired.
50 void **ppIUnk); // [out] Return interface on success.
51
52// forward declaration
53__checkReturn
54HRESULT MDApplyEditAndContinue( // S_OK or error.
55 IMDInternalImport **ppIMD, // [in, out] The metadata to be updated.
56 IMDInternalImportENC *pDeltaMD); // [in] The delta metadata.
57
58
59//*****************************************************************************
60// Constructor
61//*****************************************************************************
62MDInternalRO::MDInternalRO()
63 : m_pMethodSemanticsMap(0),
64 m_cRefs(1)
65{
66} // MDInternalRO::MDInternalRO
67
68
69
70//*****************************************************************************
71// Destructor
72//*****************************************************************************
73MDInternalRO::~MDInternalRO()
74{
75 m_LiteWeightStgdb.Uninit();
76 if (m_pMethodSemanticsMap)
77 delete[] m_pMethodSemanticsMap;
78 m_pMethodSemanticsMap = 0;
79} // MDInternalRO::~MDInternalRO
80
81//*****************************************************************************
82// IUnknown
83//*****************************************************************************
84ULONG MDInternalRO::AddRef()
85{
86 return InterlockedIncrement(&m_cRefs);
87} // MDInternalRO::AddRef
88
89ULONG MDInternalRO::Release()
90{
91 ULONG cRef = InterlockedDecrement(&m_cRefs);
92 if (cRef == 0)
93 delete this;
94 return cRef;
95} // MDInternalRO::Release
96
97__checkReturn
98HRESULT MDInternalRO::QueryInterface(REFIID riid, void **ppUnk)
99{
100 *ppUnk = 0;
101
102 if (riid == IID_IUnknown)
103 *ppUnk = this; // ! QI for IID_IUnknown must return MDInternalRO. ConvertRO2RW() has dependency on this.
104 else if (riid == IID_IMDInternalImport)
105 *ppUnk = (IMDInternalImport *)this;
106 else if (riid == IID_IMDCommon)
107 *ppUnk = (IMDCommon *)this;
108 else
109 return E_NOINTERFACE;
110 AddRef();
111 return S_OK;
112} // MDInternalRO::QueryInterface
113
114
115//*****************************************************************************
116// Initialize
117//*****************************************************************************
118__checkReturn
119HRESULT MDInternalRO::Init(
120 LPVOID pData, // points to meta data section in memory
121 ULONG cbData) // count of bytes in pData
122{
123 m_tdModule = COR_GLOBAL_PARENT_TOKEN;
124
125 extern HRESULT _CallInitOnMemHelper(CLiteWeightStgdb<CMiniMd> *pStgdb, ULONG cbData, LPCVOID pData);
126
127 return _CallInitOnMemHelper(&m_LiteWeightStgdb, cbData, (BYTE*) pData);
128} // MDInternalRO::Init
129
130#ifndef DACCESS_COMPILE
131//*****************************************************************************
132// Given a scope, determine whether imported from a typelib.
133//*****************************************************************************
134__checkReturn
135HRESULT MDInternalRO::TranslateSigWithScope(
136 IMDInternalImport* pAssemImport, // [IN] import assembly scope.
137 const void* pbHashValue, // [IN] hash value for the import assembly.
138 ULONG cbHashValue, // [IN] count of bytes in the hash value.
139 PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope
140 ULONG cbSigBlob, // [IN] count of bytes of signature
141 IMetaDataAssemblyEmit* pAssemEmit, // [IN] assembly emit scope.
142 IMetaDataEmit* emit, // [IN] emit interface
143 CQuickBytes* pqkSigEmit, // [OUT] buffer to hold translated signature
144 ULONG* pcbSig) // [OUT] count of bytes in the translated signature
145{
146 return TranslateSigHelper(
147 this,
148 pAssemImport,
149 pbHashValue,
150 cbHashValue,
151 pbSigBlob,
152 cbSigBlob,
153 pAssemEmit,
154 emit,
155 pqkSigEmit,
156 pcbSig);
157} // MDInternalRO::TranslateSigWithScope
158#endif // DACCESS_COMPILE
159
160__checkReturn
161HRESULT MDInternalRO::GetTypeDefRefTokenInTypeSpec(// return S_FALSE if enclosing type does not have a token
162 mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look at
163 mdToken *tkEnclosedToken) // [OUT] The enclosed type token
164{
165 return m_LiteWeightStgdb.m_MiniMd.GetTypeDefRefTokenInTypeSpec(tkTypeSpec, tkEnclosedToken);
166} // MDInternalRO::GetTypeDefRefTokenInTypeSpec
167
168#ifndef DACCESS_COMPILE
169//*****************************************************************************
170// Given a scope, return the number of tokens in a given table
171//*****************************************************************************
172ULONG MDInternalRO::GetCountWithTokenKind( // return hresult
173 DWORD tkKind) // [IN] pass in the kind of token.
174{
175 ULONG ulCount = m_LiteWeightStgdb.m_MiniMd.CommonGetRowCount(tkKind);
176 if (tkKind == mdtTypeDef)
177 {
178 // Remove global typedef from the count of typedefs (and handle the case where there is no global typedef)
179 if (ulCount > 0)
180 ulCount--;
181 }
182 return ulCount;
183} // MDInternalRO::GetCountWithTokenKind
184#endif //!DACCESS_COMPILE
185
186//*******************************************************************************
187// Enumerator helpers
188//*******************************************************************************
189
190
191//*****************************************************************************
192// enumerator init for typedef
193//*****************************************************************************
194__checkReturn
195HRESULT MDInternalRO::EnumTypeDefInit( // return hresult
196 HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
197{
198 HRESULT hr = NOERROR;
199
200 _ASSERTE(phEnum);
201
202 memset(phEnum, 0, sizeof(HENUMInternal));
203 phEnum->m_tkKind = mdtTypeDef;
204 phEnum->m_EnumType = MDSimpleEnum;
205 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs();
206
207 // Skip over the global model typedef
208 //
209 // phEnum->u.m_ulCur : the current rid that is not yet enumerated
210 // phEnum->u.m_ulStart : the first rid that will be returned by enumerator
211 // phEnum->u.m_ulEnd : the last rid that will be returned by enumerator
212 phEnum->u.m_ulStart = phEnum->u.m_ulCur = 2;
213 phEnum->u.m_ulEnd = phEnum->m_ulCount + 1;
214 if (phEnum->m_ulCount > 0)
215 phEnum->m_ulCount --;
216
217 return hr;
218} // MDInternalRO::EnumTypeDefInit
219
220
221//*****************************************************************************
222// get the number of typedef in a scope
223//*****************************************************************************
224ULONG MDInternalRO::EnumTypeDefGetCount(
225 HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
226{
227 _ASSERTE(phEnum->m_tkKind == mdtTypeDef);
228 return phEnum->m_ulCount;
229} // MDInternalRO::EnumTypeDefGetCount
230
231
232//*****************************************************************************
233// enumerator for typedef
234//*****************************************************************************
235bool MDInternalRO::EnumTypeDefNext( // return hresult
236 HENUMInternal *phEnum, // [IN] input enum
237 mdTypeDef *ptd) // [OUT] return token
238{
239 _ASSERTE(phEnum && ptd);
240
241 if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd)
242 return false;
243
244 *ptd = phEnum->u.m_ulCur++;
245 RidToToken(*ptd, mdtTypeDef);
246 return true;
247} // MDInternalRO::EnumTypeDefNext
248
249
250//*****************************************
251// Reset the enumerator to the beginning.
252//*****************************************
253void MDInternalRO::EnumTypeDefReset(
254 HENUMInternal *phEnum) // [IN] the enumerator to be reset
255{
256 _ASSERTE(phEnum);
257 _ASSERTE( phEnum->m_EnumType == MDSimpleEnum );
258
259 // not using CRCURSOR
260 phEnum->u.m_ulCur = phEnum->u.m_ulStart;
261} // MDInternalRO::EnumTypeDefReset
262
263
264//*****************************************
265// Close the enumerator. Only for read/write mode that we need to close the cursor.
266// Hopefully with readonly mode, it will be a no-op
267//*****************************************
268void MDInternalRO::EnumTypeDefClose(
269 HENUMInternal *phEnum) // [IN] the enumerator to be closed
270{
271 _ASSERTE( phEnum->m_EnumType == MDSimpleEnum );
272} // MDInternalRO::EnumTypeDefClose
273
274
275//*****************************************************************************
276// Enumerator init for MethodImpl. The second HENUMInternal* parameter is
277// only used for the R/W version of the MetaData.
278//*****************************************************************************
279__checkReturn
280HRESULT MDInternalRO::EnumMethodImplInit( // return hresult
281 mdTypeDef td, // [IN] TypeDef over which to scope the enumeration.
282 HENUMInternal *phEnumBody, // [OUT] buffer to fill for enumerator data for MethodBody tokens.
283 HENUMInternal *phEnumDecl) // [OUT] buffer to fill for enumerator data for MethodDecl tokens.
284{
285 return EnumInit(TBL_MethodImpl << 24, td, phEnumBody);
286} // MDInternalRO::EnumMethodImplInit
287
288//*****************************************************************************
289// get the number of MethodImpls in a scope
290//*****************************************************************************
291ULONG MDInternalRO::EnumMethodImplGetCount(
292 HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
293 HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
294{
295 _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl));
296 return phEnumBody->m_ulCount;
297} // MDInternalRO::EnumMethodImplGetCount
298
299
300//*****************************************************************************
301// enumerator for MethodImpl.
302//*****************************************************************************
303__checkReturn
304HRESULT
305MDInternalRO::EnumMethodImplNext( // return hresult
306 HENUMInternal *phEnumBody, // [IN] input enum for MethodBody
307 HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl
308 mdToken *ptkBody, // [OUT] return token for MethodBody
309 mdToken *ptkDecl) // [OUT] return token for MethodDecl
310{
311 HRESULT hr;
312 MethodImplRec *pRecord;
313
314 _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl));
315 _ASSERTE(ptkBody && ptkDecl);
316
317 if (phEnumBody->u.m_ulCur >= phEnumBody->u.m_ulEnd)
318 {
319 return S_FALSE;
320 }
321
322 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodImplRecord(phEnumBody->u.m_ulCur, &pRecord));
323 *ptkBody = m_LiteWeightStgdb.m_MiniMd.getMethodBodyOfMethodImpl(pRecord);
324 *ptkDecl = m_LiteWeightStgdb.m_MiniMd.getMethodDeclarationOfMethodImpl(pRecord);
325 phEnumBody->u.m_ulCur++;
326
327 return S_OK;
328} // MDInternalRO::EnumMethodImplNext
329
330//*****************************************
331// Reset the enumerator to the beginning.
332//*****************************************
333void MDInternalRO::EnumMethodImplReset(
334 HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
335 HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
336{
337 _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl));
338 _ASSERTE(phEnumBody->m_EnumType == MDSimpleEnum);
339
340 phEnumBody->u.m_ulCur = phEnumBody->u.m_ulStart;
341} // MDInternalRO::EnumMethodImplReset
342
343
344//*****************************************
345// Close the enumerator.
346//*****************************************
347void MDInternalRO::EnumMethodImplClose(
348 HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
349 HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
350{
351 _ASSERTE(phEnumBody && ((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl));
352 _ASSERTE(phEnumBody->m_EnumType == MDSimpleEnum);
353} // MDInternalRO::EnumMethodImplClose
354
355
356//******************************************************************************
357// enumerator for global functions
358//******************************************************************************
359__checkReturn
360HRESULT MDInternalRO::EnumGlobalFunctionsInit( // return hresult
361 HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
362{
363 return EnumInit(mdtMethodDef, m_tdModule, phEnum);
364}
365
366
367//******************************************************************************
368// enumerator for global Fields
369//******************************************************************************
370__checkReturn
371HRESULT MDInternalRO::EnumGlobalFieldsInit( // return hresult
372 HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
373{
374 return EnumInit(mdtFieldDef, m_tdModule, phEnum);
375}
376
377
378//*****************************************
379// Enumerator initializer
380//*****************************************
381__checkReturn
382HRESULT MDInternalRO::EnumInit( // return S_FALSE if record not found
383 DWORD tkKind, // [IN] which table to work on
384 mdToken tkParent, // [IN] token to scope the search
385 HENUMInternal *phEnum) // [OUT] the enumerator to fill
386{
387 HRESULT hr = S_OK;
388 ULONG ulMax = 0;
389
390 // Vars for query.
391 _ASSERTE(phEnum);
392 HENUMInternal::ZeroEnum(phEnum);
393
394 // cache the tkKind and the scope
395 phEnum->m_tkKind = TypeFromToken(tkKind);
396
397 TypeDefRec *pRec;
398
399 phEnum->m_EnumType = MDSimpleEnum;
400
401 switch (TypeFromToken(tkKind))
402 {
403 case mdtFieldDef:
404 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(tkParent), &pRec));
405 phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getFieldListOfTypeDef(pRec);
406 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(tkParent), &(phEnum->u.m_ulEnd)));
407 break;
408
409 case mdtMethodDef:
410 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(tkParent), &pRec));
411 phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getMethodListOfTypeDef(pRec);
412 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(tkParent), &(phEnum->u.m_ulEnd)));
413 break;
414
415 case mdtGenericParam:
416 _ASSERTE(TypeFromToken(tkParent) == mdtTypeDef || TypeFromToken(tkParent) == mdtMethodDef);
417
418 if (TypeFromToken(tkParent) != mdtTypeDef && TypeFromToken(tkParent) != mdtMethodDef)
419 IfFailGo(CLDB_E_FILE_CORRUPT);
420
421 if (TypeFromToken(tkParent) == mdtTypeDef)
422 {
423 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamsForTypeDef(
424 RidFromToken(tkParent),
425 &phEnum->u.m_ulEnd,
426 &(phEnum->u.m_ulStart)));
427 }
428 else
429 {
430 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamsForMethodDef(
431 RidFromToken(tkParent),
432 &phEnum->u.m_ulEnd,
433 &(phEnum->u.m_ulStart)));
434 }
435 break;
436
437 case mdtGenericParamConstraint:
438 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getGenericParamConstraintsForGenericParam(
439 RidFromToken(tkParent),
440 &phEnum->u.m_ulEnd,
441 &phEnum->u.m_ulStart));
442 break;
443
444 case mdtInterfaceImpl:
445 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getInterfaceImplsForTypeDef(RidFromToken(tkParent), &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart));
446 break;
447
448 case mdtProperty:
449 RID ridPropertyMap;
450 PropertyMapRec *pPropertyMapRec;
451
452 // get the starting/ending rid of properties of this typedef
453 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindPropertyMapFor(RidFromToken(tkParent), &ridPropertyMap));
454 if (!InvalidRid(ridPropertyMap))
455 {
456 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pPropertyMapRec));
457 phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getPropertyListOfPropertyMap(pPropertyMapRec);
458 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndPropertyListOfPropertyMap(ridPropertyMap, &(phEnum->u.m_ulEnd)));
459 ulMax = m_LiteWeightStgdb.m_MiniMd.getCountPropertys() + 1;
460 if(phEnum->u.m_ulStart == 0) phEnum->u.m_ulStart = 1;
461 if(phEnum->u.m_ulEnd > ulMax) phEnum->u.m_ulEnd = ulMax;
462 if(phEnum->u.m_ulStart > phEnum->u.m_ulEnd) phEnum->u.m_ulStart = phEnum->u.m_ulEnd;
463 }
464 break;
465
466 case mdtEvent:
467 RID ridEventMap;
468 EventMapRec *pEventMapRec;
469
470 // get the starting/ending rid of events of this typedef
471 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindEventMapFor(RidFromToken(tkParent), &ridEventMap));
472 if (!InvalidRid(ridEventMap))
473 {
474 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventMapRecord(ridEventMap, &pEventMapRec));
475 phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getEventListOfEventMap(pEventMapRec);
476 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndEventListOfEventMap(ridEventMap, &(phEnum->u.m_ulEnd)));
477 ulMax = m_LiteWeightStgdb.m_MiniMd.getCountEvents() + 1;
478 if(phEnum->u.m_ulStart == 0) phEnum->u.m_ulStart = 1;
479 if(phEnum->u.m_ulEnd > ulMax) phEnum->u.m_ulEnd = ulMax;
480 if(phEnum->u.m_ulStart > phEnum->u.m_ulEnd) phEnum->u.m_ulStart = phEnum->u.m_ulEnd;
481 }
482 break;
483
484 case mdtParamDef:
485 _ASSERTE(TypeFromToken(tkParent) == mdtMethodDef);
486
487 MethodRec *pMethodRec;
488 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(tkParent), &pMethodRec));
489
490 // figure out the start rid and end rid of the parameter list of this methoddef
491 phEnum->u.m_ulStart = m_LiteWeightStgdb.m_MiniMd.getParamListOfMethod(pMethodRec);
492 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndParamListOfMethod(RidFromToken(tkParent), &(phEnum->u.m_ulEnd)));
493 break;
494 case mdtCustomAttribute:
495 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getCustomAttributeForToken(tkParent, &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart));
496 break;
497 case mdtAssemblyRef:
498 _ASSERTE(IsNilToken(tkParent));
499 phEnum->u.m_ulStart = 1;
500 phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs() + 1;
501 break;
502 case mdtFile:
503 _ASSERTE(IsNilToken(tkParent));
504 phEnum->u.m_ulStart = 1;
505 phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountFiles() + 1;
506 break;
507 case mdtExportedType:
508 _ASSERTE(IsNilToken(tkParent));
509 phEnum->u.m_ulStart = 1;
510 phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountExportedTypes() + 1;
511 break;
512 case mdtManifestResource:
513 _ASSERTE(IsNilToken(tkParent));
514 phEnum->u.m_ulStart = 1;
515 phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountManifestResources() + 1;
516 break;
517 case mdtModuleRef:
518 _ASSERTE(IsNilToken(tkParent));
519 phEnum->u.m_ulStart = 1;
520 phEnum->u.m_ulEnd = m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs() + 1;
521 break;
522 case (TBL_MethodImpl << 24):
523 _ASSERTE(! IsNilToken(tkParent));
524 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getMethodImplsForClass(
525 RidFromToken(tkParent),
526 &phEnum->u.m_ulEnd,
527 &phEnum->u.m_ulStart));
528 break;
529 default:
530 _ASSERTE(!"ENUM INIT not implemented for the compressed format!");
531 IfFailGo(E_NOTIMPL);
532 break;
533 }
534
535 // If the count is negative, the metadata is corrupted somehow.
536 if (phEnum->u.m_ulEnd < phEnum->u.m_ulStart)
537 IfFailGo(CLDB_E_FILE_CORRUPT);
538
539 phEnum->m_ulCount = phEnum->u.m_ulEnd - phEnum->u.m_ulStart;
540 phEnum->u.m_ulCur = phEnum->u.m_ulStart;
541
542ErrExit:
543 // we are done
544 return hr;
545}
546
547
548//*****************************************
549// Enumerator initializer
550//*****************************************
551__checkReturn
552HRESULT MDInternalRO::EnumAllInit( // return S_FALSE if record not found
553 DWORD tkKind, // [IN] which table to work on
554 HENUMInternal *phEnum) // [OUT] the enumerator to fill
555{
556 HRESULT hr = S_OK;
557
558 // Vars for query.
559 _ASSERTE(phEnum);
560 memset(phEnum, 0, sizeof(HENUMInternal));
561
562 // cache the tkKind and the scope
563 phEnum->m_tkKind = TypeFromToken(tkKind);
564 phEnum->m_EnumType = MDSimpleEnum;
565
566 switch (TypeFromToken(tkKind))
567 {
568 case mdtTypeRef:
569 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs();
570 break;
571
572 case mdtMemberRef:
573 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMemberRefs();
574 break;
575
576 case mdtSignature:
577 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountStandAloneSigs();
578 break;
579
580 case mdtMethodDef:
581 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMethods();
582 break;
583
584 case mdtMethodSpec:
585 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountMethodSpecs();
586 break;
587
588 case mdtFieldDef:
589 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountFields();
590 break;
591
592 case mdtTypeSpec:
593 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeSpecs();
594 break;
595
596 case mdtAssemblyRef:
597 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs();
598 break;
599
600 case mdtModuleRef:
601 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs();
602 break;
603
604 case mdtTypeDef:
605 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs();
606 break;
607
608 case mdtFile:
609 phEnum->m_ulCount = m_LiteWeightStgdb.m_MiniMd.getCountFiles();
610 break;
611
612 default:
613 _ASSERTE(!"Bad token kind!");
614 break;
615 }
616 phEnum->u.m_ulStart = phEnum->u.m_ulCur = 1;
617 phEnum->u.m_ulEnd = phEnum->m_ulCount + 1;
618
619 // we are done
620 return hr;
621} // MDInternalRO::EnumAllInit
622
623
624//*****************************************
625// get the count
626//*****************************************
627ULONG MDInternalRO::EnumGetCount(
628 HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
629{
630 _ASSERTE(phEnum);
631 return phEnum->m_ulCount;
632}
633
634//*****************************************
635// Get next value contained in the enumerator
636//*****************************************
637bool MDInternalRO::EnumNext(
638 HENUMInternal *phEnum, // [IN] the enumerator to retrieve information
639 mdToken *ptk) // [OUT] token to scope the search
640{
641 _ASSERTE(phEnum && ptk);
642 if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd)
643 return false;
644
645 if ( phEnum->m_EnumType == MDSimpleEnum )
646 {
647 *ptk = phEnum->u.m_ulCur | phEnum->m_tkKind;
648 phEnum->u.m_ulCur++;
649 }
650 else
651 {
652 TOKENLIST *pdalist = (TOKENLIST *)&(phEnum->m_cursor);
653
654 _ASSERTE( phEnum->m_EnumType == MDDynamicArrayEnum );
655 *ptk = *( pdalist->Get(phEnum->u.m_ulCur++) );
656 }
657 return true;
658} // MDInternalRO::EnumNext
659
660
661//*****************************************
662// Reset the enumerator to the beginning.
663//*****************************************
664void MDInternalRO::EnumReset(
665 HENUMInternal *phEnum) // [IN] the enumerator to be reset
666{
667 _ASSERTE(phEnum);
668 _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || phEnum->m_EnumType == MDDynamicArrayEnum);
669
670 phEnum->u.m_ulCur = phEnum->u.m_ulStart;
671} // MDInternalRO::EnumReset
672
673
674//*****************************************
675// Close the enumerator. Only for read/write mode that we need to close the cursor.
676// Hopefully with readonly mode, it will be a no-op
677//*****************************************
678void MDInternalRO::EnumClose(
679 HENUMInternal *phEnum) // [IN] the enumerator to be closed
680{
681 _ASSERTE( phEnum->m_EnumType == MDSimpleEnum ||
682 phEnum->m_EnumType == MDDynamicArrayEnum ||
683 phEnum->m_EnumType == MDCustomEnum );
684 if (phEnum->m_EnumType == MDDynamicArrayEnum)
685 HENUMInternal::ClearEnum(phEnum);
686} // MDInternalRO::EnumClose
687
688
689//---------------------------------------------------------------------------------------
690//
691// Initialize enumerator of PermissionSets.
692//
693// Return Value:
694// CLDB_E_RECORD_NOTFOUND ... If record not found.
695// S_OK and empty enumeration ... If tkParent is nil token and Action is dclActionNil.
696//
697__checkReturn
698HRESULT
699MDInternalRO::EnumPermissionSetsInit(
700 mdToken tkParent, // [IN] Token to scope the search.
701 CorDeclSecurity Action, // [IN] Action to scope the search.
702 HENUMInternal *phEnum) // [OUT] Enumerator to fill.
703{
704 HRESULT hr = S_OK;
705
706 _ASSERTE(phEnum != NULL);
707 HENUMInternal::ZeroEnum(phEnum);
708
709 // cache the tkKind
710 phEnum->m_tkKind = mdtPermission;
711
712 DeclSecurityRec *pDecl;
713 RID ridCur;
714 RID ridEnd;
715
716 phEnum->m_EnumType = MDSimpleEnum;
717
718 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getDeclSecurityForToken(tkParent, &ridEnd, &ridCur));
719 if (Action != dclActionNil)
720 {
721 for (; ridCur < ridEnd; ridCur++)
722 {
723 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetDeclSecurityRecord(ridCur, &pDecl));
724 if (Action == m_LiteWeightStgdb.m_MiniMd.getActionOfDeclSecurity(pDecl))
725 {
726 // found a match
727 phEnum->u.m_ulStart = phEnum->u.m_ulCur = ridCur;
728 phEnum->u.m_ulEnd = ridCur + 1;
729 phEnum->m_ulCount = 1;
730 goto ErrExit;
731 }
732 }
733 hr = CLDB_E_RECORD_NOTFOUND;
734 }
735 else
736 {
737 phEnum->u.m_ulStart = phEnum->u.m_ulCur = ridCur;
738 phEnum->u.m_ulEnd = ridEnd;
739 phEnum->m_ulCount = ridEnd - ridCur;
740 }
741
742ErrExit:
743 return hr;
744} // MDInternalRO::EnumPermissionSetInit
745
746
747//*****************************************
748// Enumerator initializer for CustomAttributes
749//*****************************************
750__checkReturn
751HRESULT MDInternalRO::EnumCustomAttributeByNameInit(// return S_FALSE if record not found
752 mdToken tkParent, // [IN] token to scope the search
753 LPCSTR szName, // [IN] CustomAttribute's name to scope the search
754 HENUMInternal *phEnum) // [OUT] the enumerator to fill
755{
756 return m_LiteWeightStgdb.m_MiniMd.CommonEnumCustomAttributeByName(tkParent, szName, false, phEnum);
757} // MDInternalRO::EnumCustomAttributeByNameInit
758
759//*****************************************
760// Enumerator for CustomAttributes which doesn't
761// allocate any memory
762//*****************************************
763__checkReturn
764HRESULT MDInternalRO::SafeAndSlowEnumCustomAttributeByNameInit(// return S_FALSE if record not found
765 mdToken tkParent, // [IN] token to scope the search
766 LPCSTR szName, // [IN] CustomAttribute's name to scope the search
767 HENUMInternal *phEnum) // [OUT] The enumerator
768{
769 _ASSERTE(phEnum);
770
771 HRESULT hr;
772 ULONG ridStart, ridEnd; // Loop start and endpoints.
773
774 // Get the list of custom values for the parent object.
775 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getCustomAttributeForToken(tkParent, &ridEnd, &ridStart));
776 // If found none, done.
777 if (ridStart == 0)
778 goto NoMatch;
779
780 phEnum->m_EnumType = MDCustomEnum;
781 phEnum->m_tkKind = mdtCustomAttribute;
782 phEnum->u.m_ulStart = ridStart;
783 phEnum->u.m_ulEnd = ridEnd;
784 phEnum->u.m_ulCur = ridStart;
785
786 return S_OK;
787
788NoMatch:
789 return S_FALSE;
790} // MDInternalRO::SafeAndSlowEnumCustomAttributeByNameInit
791
792__checkReturn
793HRESULT MDInternalRO::SafeAndSlowEnumCustomAttributeByNameNext(// return S_FALSE if record not found
794 mdToken tkParent, // [IN] token to scope the search
795 LPCSTR szName, // [IN] CustomAttribute's name to scope the search
796 HENUMInternal *phEnum, // [IN] The enumerator
797 mdCustomAttribute *mdAttribute) // [OUT] The custom attribute that was found
798{
799 _ASSERTE(phEnum);
800 _ASSERTE(phEnum->m_EnumType == MDCustomEnum);
801 _ASSERTE(phEnum->m_tkKind == mdtCustomAttribute);
802
803 // Look for one with the given name.
804 for (; phEnum->u.m_ulCur < phEnum->u.m_ulEnd; ++phEnum->u.m_ulCur)
805 {
806 if (S_OK == m_LiteWeightStgdb.m_MiniMd.CompareCustomAttribute( tkParent, szName, phEnum->u.m_ulCur))
807 {
808 // If here, found a match.
809 *mdAttribute = TokenFromRid(phEnum->u.m_ulCur, mdtCustomAttribute);
810 phEnum->u.m_ulCur++;
811 return S_OK;
812 }
813 }
814 // No match...
815 return S_FALSE;
816} // MDInternalRO::SafeAndSlowEnumCustomAttributeByNameNext
817
818
819//*****************************************
820// Nagivator helper to navigate back to the parent token given a token.
821// For example, given a memberdef token, it will return the containing typedef.
822//
823// the mapping is as following:
824// ---given child type---------parent type
825// mdMethodDef mdTypeDef
826// mdFieldDef mdTypeDef
827// mdInterfaceImpl mdTypeDef
828// mdParam mdMethodDef
829// mdProperty mdTypeDef
830// mdEvent mdTypeDef
831//
832//*****************************************
833__checkReturn
834HRESULT MDInternalRO::GetParentToken(
835 mdToken tkChild, // [IN] given child token
836 mdToken *ptkParent) // [OUT] returning parent
837{
838 HRESULT hr = NOERROR;
839
840 _ASSERTE(ptkParent);
841
842 switch (TypeFromToken(tkChild))
843 {
844 case mdtTypeDef:
845 hr = GetNestedClassProps(tkChild, ptkParent);
846 // If not found, the *ptkParent has to be left unchanged! (callers depend on that)
847 if (hr == CLDB_E_RECORD_NOTFOUND)
848 {
849 hr = S_OK;
850 }
851 break;
852
853 case mdtMethodDef:
854 IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfMethod(RidFromToken(tkChild), (RID *)ptkParent));
855 RidToToken(*ptkParent, mdtTypeDef);
856 break;
857
858 case mdtMethodSpec:
859 {
860 MethodSpecRec *pRec;
861 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSpecRecord(RidFromToken(tkChild), &pRec));
862 *ptkParent = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSpec(pRec);
863 break;
864 }
865
866 case mdtFieldDef:
867 IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfField(RidFromToken(tkChild), (RID *)ptkParent));
868 RidToToken(*ptkParent, mdtTypeDef);
869 break;
870
871 case mdtParamDef:
872 IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindParentOfParam(RidFromToken(tkChild), (RID *)ptkParent));
873 RidToToken(*ptkParent, mdtMethodDef);
874 break;
875
876 case mdtMemberRef:
877 {
878 MemberRefRec *pRec;
879 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(tkChild), &pRec));
880 *ptkParent = m_LiteWeightStgdb.m_MiniMd.getClassOfMemberRef(pRec);
881 break;
882 }
883
884 case mdtCustomAttribute:
885 {
886 CustomAttributeRec *pRec;
887 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(tkChild), &pRec));
888 *ptkParent = m_LiteWeightStgdb.m_MiniMd.getParentOfCustomAttribute(pRec);
889 break;
890 }
891
892 case mdtEvent:
893 hr = m_LiteWeightStgdb.m_MiniMd.FindParentOfEventHelper(tkChild, ptkParent);
894 break;
895
896 case mdtProperty:
897 hr = m_LiteWeightStgdb.m_MiniMd.FindParentOfPropertyHelper(tkChild, ptkParent);
898 break;
899
900 default:
901 _ASSERTE(!"NYI: for compressed format!");
902 break;
903 }
904 return hr;
905} // MDInternalRO::GetParentToken
906
907
908
909//*****************************************************************************
910// Get information about a CustomAttribute.
911//*****************************************************************************
912__checkReturn
913HRESULT
914MDInternalRO::GetCustomAttributeProps( // S_OK or error.
915 mdCustomAttribute at, // The attribute.
916 mdToken *ptkType) // Put attribute type here.
917{
918 HRESULT hr;
919 _ASSERTE(TypeFromToken(at) == mdtCustomAttribute);
920
921 // Do a linear search on compressed version as we do not want to
922 // depends on ICR.
923 //
924 CustomAttributeRec *pCustomAttributeRec;
925
926 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(at), &pCustomAttributeRec));
927 *ptkType = m_LiteWeightStgdb.m_MiniMd.getTypeOfCustomAttribute(pCustomAttributeRec);
928 return S_OK;
929} // MDInternalRO::GetCustomAttributeProps
930
931//*****************************************************************************
932// return custom value
933//*****************************************************************************
934__checkReturn
935HRESULT
936MDInternalRO::GetCustomAttributeAsBlob(
937 mdCustomAttribute cv, // [IN] given custom attribute token
938 void const **ppBlob, // [OUT] return the pointer to internal blob
939 ULONG *pcbSize) // [OUT] return the size of the blob
940{
941 HRESULT hr;
942 _ASSERTE(ppBlob && pcbSize && TypeFromToken(cv) == mdtCustomAttribute);
943
944 CustomAttributeRec *pCustomAttributeRec;
945
946 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetCustomAttributeRecord(RidFromToken(cv), &pCustomAttributeRec));
947
948 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getValueOfCustomAttribute(pCustomAttributeRec, (const BYTE **)ppBlob, pcbSize));
949 return S_OK;
950} // MDInternalRO::GetCustomAttributeAsBlob
951
952//*****************************************************************************
953// Helper function to lookup and retrieve a CustomAttribute.
954//*****************************************************************************
955__checkReturn
956HRESULT MDInternalRO::GetCustomAttributeByName( // S_OK or error.
957 mdToken tkObj, // [IN] Object with Custom Attribute.
958 LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
959 __deref_out_bcount(*pcbData) const void **ppData, // [OUT] Put pointer to data here.
960 __out ULONG *pcbData) // [OUT] Put size of data here.
961{
962 return m_LiteWeightStgdb.m_MiniMd.CommonGetCustomAttributeByName(tkObj, szName, ppData, pcbData);
963} // MDInternalRO::GetCustomAttributeByName
964
965
966//*****************************************************************************
967// return the name of a custom attribute
968//*****************************************************************************
969__checkReturn
970HRESULT MDInternalRO::GetNameOfCustomAttribute( // S_OK or error.
971 mdCustomAttribute mdAttribute, // [IN] The Custom Attribute
972 LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute.
973 LPCUTF8 *pszName) // [OUT] Name of Custom Attribute.
974{
975 _ASSERTE(TypeFromToken(mdAttribute) == mdtCustomAttribute);
976
977 HRESULT hr = m_LiteWeightStgdb.m_MiniMd.CommonGetNameOfCustomAttribute(RidFromToken(mdAttribute), pszNamespace, pszName);
978 return (hr == S_FALSE) ? E_FAIL : hr;
979} // MDInternalRO::GetNameOfCustomAttribute
980
981//*****************************************************************************
982// return scope properties
983//*****************************************************************************
984__checkReturn
985HRESULT
986MDInternalRO::GetScopeProps(
987 LPCSTR *pszName, // [OUT] scope name
988 GUID *pmvid) // [OUT] version id
989{
990 HRESULT hr;
991
992 ModuleRec *pModuleRec;
993
994 // there is only one module record
995 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetModuleRecord(1, &pModuleRec));
996
997 if (pmvid != NULL)
998 {
999 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getMvidOfModule(pModuleRec, pmvid));
1000 }
1001 if (pszName != NULL)
1002 {
1003 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfModule(pModuleRec, pszName));
1004 }
1005
1006 return S_OK;
1007} // MDInternalRO::GetScopeProps
1008
1009
1010//*****************************************************************************
1011// Compare two signatures from the same scope. Varags signatures need to be
1012// preprocessed so they only contain the fixed part.
1013//*****************************************************************************
1014BOOL MDInternalRO::CompareSignatures(PCCOR_SIGNATURE pvFirstSigBlob, // First signature
1015 DWORD cbFirstSigBlob, //
1016 PCCOR_SIGNATURE pvSecondSigBlob, // Second signature
1017 DWORD cbSecondSigBlob, //
1018 void * SigArguments) // No additional arguments required
1019{
1020 if (cbFirstSigBlob != cbSecondSigBlob || memcmp(pvFirstSigBlob, pvSecondSigBlob, cbSecondSigBlob))
1021 return FALSE;
1022 else
1023 return TRUE;
1024}
1025
1026//*****************************************************************************
1027// Find a given member in a TypeDef (typically a class).
1028//*****************************************************************************
1029__checkReturn
1030HRESULT MDInternalRO::FindMethodDef( // S_OK or error.
1031 mdTypeDef classdef, // The owning class of the member.
1032 LPCSTR szName, // Name of the member in utf8.
1033 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
1034 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
1035 mdMethodDef *pmethoddef) // Put MemberDef token here.
1036{
1037
1038 return FindMethodDefUsingCompare(classdef,
1039 szName,
1040 pvSigBlob,
1041 cbSigBlob,
1042 CompareSignatures,
1043 NULL,
1044 pmethoddef);
1045}
1046
1047//*****************************************************************************
1048// Find a given member in a TypeDef (typically a class).
1049//*****************************************************************************
1050__checkReturn
1051HRESULT MDInternalRO::FindMethodDefUsingCompare( // S_OK or error.
1052 mdTypeDef classdef, // The owning class of the member.
1053 LPCSTR szName, // Name of the member in utf8.
1054 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
1055 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
1056 PSIGCOMPARE SigCompare, // [IN] Signature comparison routine
1057 void* pSigArgs, // [IN] Additional arguments passed to signature compare
1058 mdMethodDef *pmethoddef) // Put MemberDef token here.
1059{
1060 HRESULT hr = NOERROR;
1061 PCCOR_SIGNATURE pvSigTemp = pvSigBlob;
1062 CQuickBytes qbSig;
1063
1064 _ASSERTE(szName && pmethoddef);
1065
1066 // initialize the output parameter
1067 *pmethoddef = mdMethodDefNil;
1068
1069 // check to see if this is a vararg signature
1070 if ( isCallConv(CorSigUncompressCallingConv(pvSigTemp), IMAGE_CEE_CS_CALLCONV_VARARG) )
1071 {
1072 // Get the fix part of VARARG signature
1073 IfFailGo( _GetFixedSigOfVarArg(pvSigBlob, cbSigBlob, &qbSig, &cbSigBlob) );
1074 pvSigBlob = (PCCOR_SIGNATURE) qbSig.Ptr();
1075 }
1076
1077 // Do a linear search on compressed version
1078 //
1079 RID ridMax;
1080 MethodRec *pMethodRec;
1081 LPCUTF8 szCurMethodName;
1082 void const *pvCurMethodSig;
1083 ULONG cbSig;
1084 TypeDefRec *pRec;
1085 RID ridStart;
1086
1087 // get the typedef record
1088 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(classdef), &pRec));
1089
1090 // get the range of methoddef rids given the classdef
1091 ridStart = m_LiteWeightStgdb.m_MiniMd.getMethodListOfTypeDef(pRec);
1092 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(classdef), &ridMax));
1093
1094 // loop through each methoddef
1095 for (; ridStart < ridMax; ridStart++)
1096 {
1097 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(ridStart, &pMethodRec));
1098 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfMethod(pMethodRec, &szCurMethodName));
1099 if (strcmp(szCurMethodName, szName) == 0)
1100 {
1101 // name match, now check the signature if specified.
1102 if (cbSigBlob && SigCompare)
1103 {
1104 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, (PCCOR_SIGNATURE *)&pvCurMethodSig, &cbSig));
1105 // Signature comparison is required
1106 // Note that if pvSigBlob is vararg, we already preprocess it so that
1107 // it only contains the fix part. Therefore, it still should be an exact
1108 // match!!!.
1109 //
1110 if(SigCompare((PCCOR_SIGNATURE) pvCurMethodSig, cbSig, pvSigBlob, cbSigBlob, pSigArgs) == FALSE)
1111 continue;
1112 }
1113 // Ignore PrivateScope methods.
1114 if (IsMdPrivateScope(m_LiteWeightStgdb.m_MiniMd.getFlagsOfMethod(pMethodRec)))
1115 continue;
1116 // found the match
1117 *pmethoddef = TokenFromRid(ridStart, mdtMethodDef);
1118 goto ErrExit;
1119 }
1120 }
1121 hr = CLDB_E_RECORD_NOTFOUND;
1122
1123ErrExit:
1124 return hr;
1125}
1126
1127//*****************************************************************************
1128// Find a given param of a Method.
1129//*****************************************************************************
1130__checkReturn
1131HRESULT MDInternalRO::FindParamOfMethod(// S_OK or error.
1132 mdMethodDef md, // [IN] The owning method of the param.
1133 ULONG iSeq, // [IN] The sequence # of the param.
1134 mdParamDef *pparamdef) // [OUT] Put ParamDef token here.
1135{
1136 HRESULT hr;
1137 ParamRec *pParamRec;
1138 RID ridStart, ridEnd;
1139
1140 _ASSERTE(TypeFromToken(md) == mdtMethodDef && pparamdef);
1141
1142 // get the methoddef record
1143 MethodRec *pMethodRec;
1144 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
1145
1146 // figure out the start rid and end rid of the parameter list of this methoddef
1147 ridStart = m_LiteWeightStgdb.m_MiniMd.getParamListOfMethod(pMethodRec);
1148 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getEndParamListOfMethod(RidFromToken(md), &ridEnd));
1149
1150 // Ensure that the paramList is valid. If the count is negative, the metadata
1151 // is corrupted somehow. Thus, return CLDB_E_FILE_CORRUPT.
1152 if (ridEnd < ridStart)
1153 return CLDB_E_FILE_CORRUPT;
1154
1155 // loop through each param
1156 //<TODO>@consider: parameters are sorted by sequence. Maybe a binary search?
1157 //</TODO>
1158 for (; ridStart < ridEnd; ridStart++)
1159 {
1160 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetParamRecord(ridStart, &pParamRec));
1161 if (iSeq == m_LiteWeightStgdb.m_MiniMd.getSequenceOfParam(pParamRec))
1162 {
1163 // parameter has the sequence number matches what we are looking for
1164 *pparamdef = TokenFromRid(ridStart, mdtParamDef);
1165 return S_OK;
1166 }
1167 }
1168 return CLDB_E_RECORD_NOTFOUND;
1169}
1170
1171
1172
1173//*****************************************************************************
1174// return a pointer which points to meta data's internal string
1175// return the the type name in utf8
1176//*****************************************************************************
1177__checkReturn
1178HRESULT
1179MDInternalRO::GetNameOfTypeDef( // return hresult
1180 mdTypeDef classdef, // given typedef
1181 LPCSTR* pszname, // pointer to an internal UTF8 string
1182 LPCSTR* psznamespace) // pointer to the namespace.
1183{
1184 HRESULT hr;
1185
1186 if (pszname != NULL)
1187 {
1188 *pszname = NULL;
1189 }
1190 if (psznamespace != NULL)
1191 {
1192 *psznamespace = NULL;
1193 }
1194
1195 if (TypeFromToken(classdef) == mdtTypeDef)
1196 {
1197 TypeDefRec *pTypeDefRec;
1198 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(classdef), &pTypeDefRec));
1199
1200 if (pszname != NULL)
1201 {
1202 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeDef(pTypeDefRec, pszname));
1203 }
1204
1205 if (psznamespace != NULL)
1206 {
1207 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeDef(pTypeDefRec, psznamespace));
1208 }
1209 return S_OK;
1210 }
1211
1212 _ASSERTE(!"Invalid argument(s) of GetNameOfTypeDef");
1213 return CLDB_E_INTERNALERROR;
1214} // MDInternalRO::GetNameOfTypeDef
1215
1216
1217__checkReturn
1218HRESULT MDInternalRO::GetIsDualOfTypeDef(// return hresult
1219 mdTypeDef classdef, // given classdef
1220 ULONG *pDual) // [OUT] return dual flag here.
1221{
1222 ULONG iFace=0; // Iface type.
1223 HRESULT hr; // A result.
1224
1225 hr = GetIfaceTypeOfTypeDef(classdef, &iFace);
1226 if (hr == S_OK)
1227 *pDual = (iFace == ifDual);
1228 else
1229 *pDual = 1;
1230
1231 return hr;
1232} // MDInternalRO::GetIsDualOfTypeDef
1233
1234__checkReturn
1235HRESULT MDInternalRO::GetIfaceTypeOfTypeDef(
1236 mdTypeDef classdef, // [IN] given classdef.
1237 ULONG *pIface) // [OUT] 0=dual, 1=vtable, 2=dispinterface
1238{
1239 HRESULT hr; // A result.
1240 const BYTE *pVal; // The custom value.
1241 ULONG cbVal; // Size of the custom value.
1242 ULONG ItfType = DEFAULT_COM_INTERFACE_TYPE; // Set the interface type to the default.
1243
1244 // If the value is not present, the class is assumed dual.
1245 hr = GetCustomAttributeByName(classdef, INTEROP_INTERFACETYPE_TYPE, (const void**)&pVal, &cbVal);
1246 if (hr == S_OK)
1247 {
1248 CustomAttributeParser cap(pVal, cbVal);
1249 BYTE u1;
1250 if (SUCCEEDED(cap.SkipProlog()) &&
1251 SUCCEEDED(cap.GetU1(&u1)))
1252 {
1253 ItfType = u1;
1254 }
1255 if (ItfType >= ifLast)
1256 ItfType = DEFAULT_COM_INTERFACE_TYPE;
1257 }
1258
1259 // Set the return value.
1260 *pIface = ItfType;
1261
1262 return hr;
1263} // MDInternalRO::GetIfaceTypeOfTypeDef
1264
1265//*****************************************************************************
1266// Given a methoddef, return a pointer to methoddef's name
1267//*****************************************************************************
1268__checkReturn
1269HRESULT
1270MDInternalRO::GetNameOfMethodDef(
1271 mdMethodDef md,
1272 LPCSTR *pszMethodName)
1273{
1274 HRESULT hr;
1275 MethodRec *pMethodRec;
1276 *pszMethodName = NULL;
1277 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
1278 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfMethod(pMethodRec, pszMethodName));
1279 return S_OK;
1280} // MDInternalRO::GetNameOfMethodDef
1281
1282//*****************************************************************************
1283// Given a methoddef, return a pointer to methoddef's signature and methoddef's name
1284//*****************************************************************************
1285__checkReturn
1286HRESULT
1287MDInternalRO::GetNameAndSigOfMethodDef(
1288 mdMethodDef methoddef, // [IN] given memberdef
1289 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature
1290 ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
1291 LPCSTR *pszMethodName)
1292{
1293 HRESULT hr;
1294 // Output parameter should not be NULL
1295 _ASSERTE(ppvSigBlob && pcbSigBlob);
1296 _ASSERTE(TypeFromToken(methoddef) == mdtMethodDef);
1297
1298 MethodRec *pMethodRec;
1299 *pszMethodName = NULL;
1300 *ppvSigBlob = NULL;
1301 *pcbSigBlob = 0;
1302 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec));
1303 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, (PCCOR_SIGNATURE *)ppvSigBlob, pcbSigBlob));
1304
1305 return GetNameOfMethodDef(methoddef, pszMethodName);
1306} // MDInternalRO::GetNameAndSigOfMethodDef
1307
1308//*****************************************************************************
1309// Given a FieldDef, return a pointer to FieldDef's name in UTF8
1310//*****************************************************************************
1311__checkReturn
1312HRESULT
1313MDInternalRO::GetNameOfFieldDef( // return hresult
1314 mdFieldDef fd, // given field
1315 LPCSTR *pszFieldName)
1316{
1317 HRESULT hr;
1318 FieldRec *pFieldRec;
1319 *pszFieldName = NULL;
1320 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec));
1321 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfField(pFieldRec, pszFieldName));
1322 return S_OK;
1323} // MDInternalRO::GetNameOfFieldDef
1324
1325
1326//*****************************************************************************
1327// Given a classdef, return the name and namespace of the typeref
1328//*****************************************************************************
1329__checkReturn
1330HRESULT
1331MDInternalRO::GetNameOfTypeRef( // return TypeDef's name
1332 mdTypeRef classref, // [IN] given typeref
1333 LPCSTR *psznamespace, // [OUT] return typeref name
1334 LPCSTR *pszname) // [OUT] return typeref namespace
1335
1336{
1337 _ASSERTE(TypeFromToken(classref) == mdtTypeRef);
1338
1339 HRESULT hr;
1340 TypeRefRec *pTypeRefRec;
1341
1342 *psznamespace = NULL;
1343 *pszname = NULL;
1344
1345 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec));
1346 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, psznamespace));
1347 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, pszname));
1348 return S_OK;
1349}
1350
1351//*****************************************************************************
1352// return the resolutionscope of typeref
1353//*****************************************************************************
1354__checkReturn
1355HRESULT
1356MDInternalRO::GetResolutionScopeOfTypeRef(
1357 mdTypeRef classref, // given classref
1358 mdToken *ptkResolutionScope)
1359{
1360 _ASSERTE(TypeFromToken(classref) == mdtTypeRef && RidFromToken(classref));
1361 HRESULT hr;
1362
1363 TypeRefRec *pTypeRefRec;
1364
1365 *ptkResolutionScope = mdTokenNil;
1366 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec));
1367 *ptkResolutionScope = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec);
1368 return S_OK;
1369} // MDInternalRO::GetResolutionScopeOfTypeRef
1370
1371//*****************************************************************************
1372// Given a name, find the corresponding TypeRef.
1373//*****************************************************************************
1374__checkReturn
1375HRESULT MDInternalRO::FindTypeRefByName( // S_OK or error.
1376 LPCSTR szNamespace, // [IN] Namespace for the TypeRef.
1377 LPCSTR szName, // [IN] Name of the TypeRef.
1378 mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef.
1379 mdTypeRef *ptk) // [OUT] TypeRef token returned.
1380{
1381 HRESULT hr = NOERROR;
1382
1383 _ASSERTE(ptk);
1384
1385 // initialize the output parameter
1386 *ptk = mdTypeRefNil;
1387
1388 // Treat no namespace as empty string.
1389 if (!szNamespace)
1390 szNamespace = "";
1391
1392 // Do a linear search on compressed version as we do not want to
1393 // depends on ICR.
1394 //
1395 ULONG cTypeRefRecs = m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs();
1396 TypeRefRec *pTypeRefRec;
1397 LPCUTF8 szNamespaceTmp;
1398 LPCUTF8 szNameTmp;
1399 mdToken tkRes;
1400
1401 for (ULONG i = 1; i <= cTypeRefRecs; i++)
1402 {
1403 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(i, &pTypeRefRec));
1404 tkRes = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec);
1405
1406 if (IsNilToken(tkRes))
1407 {
1408 if (!IsNilToken(tkResolutionScope))
1409 continue;
1410 }
1411 else if (tkRes != tkResolutionScope)
1412 continue;
1413
1414 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, &szNamespaceTmp));
1415 if (strcmp(szNamespace, szNamespaceTmp))
1416 continue;
1417
1418 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, &szNameTmp));
1419 if (!strcmp(szNameTmp, szName))
1420 {
1421 *ptk = TokenFromRid(i, mdtTypeRef);
1422 goto ErrExit;
1423 }
1424 }
1425
1426 // cannot find the typedef
1427 hr = CLDB_E_RECORD_NOTFOUND;
1428ErrExit:
1429 return hr;
1430}
1431
1432//*****************************************************************************
1433// return flags for a given class
1434//*****************************************************************************
1435__checkReturn
1436HRESULT MDInternalRO::GetTypeDefProps(
1437 mdTypeDef td, // given classdef
1438 DWORD *pdwAttr, // return flags on class
1439 mdToken *ptkExtends) // [OUT] Put base class TypeDef/TypeRef here.
1440{
1441 HRESULT hr;
1442 TypeDefRec *pTypeDefRec;
1443 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec));
1444
1445 if (ptkExtends)
1446 {
1447 *ptkExtends = m_LiteWeightStgdb.m_MiniMd.getExtendsOfTypeDef(pTypeDefRec);
1448 }
1449 if (pdwAttr)
1450 {
1451 *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfTypeDef(pTypeDefRec);
1452 }
1453
1454 return S_OK;
1455}
1456
1457
1458//*****************************************************************************
1459// return guid pointer to MetaData internal guid pool given a given class
1460//*****************************************************************************
1461__checkReturn
1462HRESULT MDInternalRO::GetItemGuid( // return hresult
1463 mdToken tkObj, // given item
1464 CLSID *pGuid)
1465{
1466
1467 HRESULT hr; // A result.
1468 const BYTE *pBlob = NULL; // Blob with dispid.
1469 ULONG cbBlob; // Length of blob.
1470 int ix; // Loop control.
1471
1472 // Get the GUID, if any.
1473 hr = GetCustomAttributeByName(tkObj, INTEROP_GUID_TYPE, (const void**)&pBlob, &cbBlob);
1474 if (hr != S_FALSE)
1475 {
1476 // Should be in format. Total length == 41
1477 // <0x0001><0x24>01234567-0123-0123-0123-001122334455<0x0000>
1478 if ((cbBlob != 41) || (GET_UNALIGNED_VAL16(pBlob) != 1))
1479 IfFailGo(E_INVALIDARG);
1480
1481 WCHAR wzBlob[40]; // Wide char format of guid.
1482 for (ix=1; ix<=36; ++ix)
1483 wzBlob[ix] = pBlob[ix+2];
1484 wzBlob[0] = '{';
1485 wzBlob[37] = '}';
1486 wzBlob[38] = 0;
1487 hr = IIDFromString(wzBlob, pGuid);
1488 }
1489 else
1490 *pGuid = GUID_NULL;
1491
1492ErrExit:
1493 return hr;
1494} // MDInternalRO::GetItemGuid
1495
1496
1497//*****************************************************************************
1498// // get enclosing class of NestedClass
1499//*****************************************************************************
1500__checkReturn
1501HRESULT MDInternalRO::GetNestedClassProps( // S_OK or error
1502 mdTypeDef tkNestedClass, // [IN] NestedClass token.
1503 mdTypeDef *ptkEnclosingClass) // [OUT] EnclosingClass token.
1504{
1505 HRESULT hr;
1506 _ASSERTE(TypeFromToken(tkNestedClass) == mdtTypeDef && ptkEnclosingClass);
1507
1508 RID rid;
1509 IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindNestedClassFor(RidFromToken(tkNestedClass), &rid));
1510
1511 if (InvalidRid(rid))
1512 {
1513 return CLDB_E_RECORD_NOTFOUND;
1514 }
1515 else
1516 {
1517 NestedClassRec *pRecord;
1518 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(rid, &pRecord));
1519 *ptkEnclosingClass = m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord);
1520 return S_OK;
1521 }
1522}
1523
1524//*******************************************************************************
1525// Get count of Nested classes given the enclosing class.
1526//*******************************************************************************
1527__checkReturn
1528HRESULT
1529MDInternalRO::GetCountNestedClasses( // return count of Nested classes.
1530 mdTypeDef tkEnclosingClass, // [IN]Enclosing class.
1531 ULONG *pcNestedClassesCount)
1532{
1533 HRESULT hr;
1534 ULONG ulCount;
1535 ULONG ulRetCount = 0;
1536 NestedClassRec *pRecord;
1537
1538 _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef && !IsNilToken(tkEnclosingClass));
1539
1540 *pcNestedClassesCount = 0;
1541
1542 ulCount = m_LiteWeightStgdb.m_MiniMd.getCountNestedClasss();
1543
1544 for (ULONG i = 1; i <= ulCount; i++)
1545 {
1546 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(i, &pRecord));
1547 if (tkEnclosingClass == m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord))
1548 ulRetCount++;
1549 }
1550 *pcNestedClassesCount = ulRetCount;
1551 return S_OK;
1552} // MDInternalRO::GetCountNestedClasses
1553
1554//*******************************************************************************
1555// Return array of Nested classes given the enclosing class.
1556//*******************************************************************************
1557__checkReturn
1558HRESULT
1559MDInternalRO::GetNestedClasses( // Return actual count.
1560 mdTypeDef tkEnclosingClass, // [IN] Enclosing class.
1561 mdTypeDef *rNestedClasses, // [OUT] Array of nested class tokens.
1562 ULONG ulNestedClasses, // [IN] Size of array.
1563 ULONG *pcNestedClasses)
1564{
1565 HRESULT hr;
1566 ULONG ulCount;
1567 ULONG ulRetCount = 0;
1568 NestedClassRec *pRecord;
1569
1570 _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef &&
1571 !IsNilToken(tkEnclosingClass));
1572
1573 *pcNestedClasses = 0;
1574
1575 ulCount = m_LiteWeightStgdb.m_MiniMd.getCountNestedClasss();
1576
1577 for (ULONG i = 1; i <= ulCount; i++)
1578 {
1579 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(i, &pRecord));
1580 if (tkEnclosingClass == m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pRecord))
1581 {
1582 if (ovadd_le(ulRetCount, 1, ulNestedClasses)) // ulRetCount is 0 based.
1583 rNestedClasses[ulRetCount] = m_LiteWeightStgdb.m_MiniMd.getNestedClassOfNestedClass(pRecord);
1584 ulRetCount++;
1585 }
1586 }
1587 *pcNestedClasses = ulRetCount;
1588 return S_OK;
1589} // MDInternalRO::GetNestedClasses
1590
1591//*******************************************************************************
1592// return the ModuleRef properties
1593//*******************************************************************************
1594__checkReturn
1595HRESULT MDInternalRO::GetModuleRefProps( // return hresult
1596 mdModuleRef mur, // [IN] moduleref token
1597 LPCSTR *pszName) // [OUT] buffer to fill with the moduleref name
1598{
1599 _ASSERTE(TypeFromToken(mur) == mdtModuleRef);
1600 _ASSERTE(pszName);
1601
1602 HRESULT hr;
1603
1604 // Is it a valid token?
1605 if (!IsValidToken(mur))
1606 {
1607 *pszName = NULL; // Not every caller checks returned HRESULT, allow to fail fast in that case
1608 return COR_E_BADIMAGEFORMAT; // Invalid Token
1609 }
1610
1611 ModuleRefRec *pModuleRefRec;
1612 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetModuleRefRecord(RidFromToken(mur), &pModuleRefRec));
1613 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfModuleRef(pModuleRefRec, pszName));
1614
1615 return S_OK;
1616}
1617
1618
1619
1620//*****************************************************************************
1621// Given a scope and a methoddef, return a pointer to methoddef's signature
1622//*****************************************************************************
1623__checkReturn
1624HRESULT
1625MDInternalRO::GetSigOfMethodDef(
1626 mdMethodDef methoddef, // given a methoddef
1627 ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
1628 PCCOR_SIGNATURE *ppSig)
1629{
1630 // Output parameter should not be NULL
1631 _ASSERTE(pcbSigBlob);
1632 _ASSERTE(TypeFromToken(methoddef) == mdtMethodDef);
1633
1634 HRESULT hr;
1635 MethodRec *pMethodRec;
1636 *ppSig = NULL;
1637 *pcbSigBlob = 0;
1638 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec));
1639 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMethod(pMethodRec, ppSig, pcbSigBlob));
1640 return S_OK;
1641} // MDInternalRO::GetSigOfMethodDef
1642
1643
1644//*****************************************************************************
1645// Given a scope and a fielddef, return a pointer to fielddef's signature
1646//*****************************************************************************
1647__checkReturn
1648HRESULT
1649MDInternalRO::GetSigOfFieldDef(
1650 mdFieldDef fielddef, // given a methoddef
1651 ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
1652 PCCOR_SIGNATURE *ppSig)
1653{
1654 _ASSERTE(pcbSigBlob);
1655 _ASSERTE(TypeFromToken(fielddef) == mdtFieldDef);
1656
1657 HRESULT hr;
1658 FieldRec *pFieldRec;
1659 *ppSig = NULL;
1660 *pcbSigBlob = 0;
1661 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fielddef), &pFieldRec));
1662 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfField(pFieldRec, ppSig, pcbSigBlob));
1663 return S_OK;
1664} // MDInternalRO::GetSigOfFieldDef
1665
1666//*****************************************************************************
1667// Get signature for the token (FieldDef, MethodDef, Signature, or TypeSpec).
1668//*****************************************************************************
1669__checkReturn
1670HRESULT
1671MDInternalRO::GetSigFromToken(
1672 mdToken tk,
1673 ULONG * pcbSig,
1674 PCCOR_SIGNATURE * ppSig)
1675{
1676 HRESULT hr;
1677
1678 *ppSig = NULL;
1679 *pcbSig = 0;
1680 switch (TypeFromToken(tk))
1681 {
1682 case mdtSignature:
1683 {
1684 StandAloneSigRec * pRec;
1685 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetStandAloneSigRecord(RidFromToken(tk), &pRec));
1686 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfStandAloneSig(pRec, ppSig, pcbSig));
1687 return S_OK;
1688 }
1689 case mdtTypeSpec:
1690 {
1691 TypeSpecRec * pRec;
1692 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeSpecRecord(RidFromToken(tk), &pRec));
1693 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfTypeSpec(pRec, ppSig, pcbSig));
1694 return S_OK;
1695 }
1696 case mdtMethodDef:
1697 {
1698 IfFailRet(GetSigOfMethodDef(tk, pcbSig, ppSig));
1699 return S_OK;
1700 }
1701 case mdtFieldDef:
1702 {
1703 IfFailRet(GetSigOfFieldDef(tk, pcbSig, ppSig));
1704 return S_OK;
1705 }
1706 }
1707
1708 // not a known token type.
1709 *pcbSig = 0;
1710 return META_E_INVALID_TOKEN_TYPE;
1711} // MDInternalRO::GetSigFromToken
1712
1713
1714//*****************************************************************************
1715// Given methoddef, return the flags
1716//*****************************************************************************
1717__checkReturn
1718HRESULT
1719MDInternalRO::GetMethodDefProps(
1720 mdMethodDef md,
1721 DWORD *pdwFlags) // return mdPublic, mdAbstract, etc
1722{
1723 HRESULT hr;
1724 MethodRec *pMethodRec;
1725
1726 *pdwFlags = (DWORD)-1;
1727 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
1728 *pdwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfMethod(pMethodRec);
1729
1730 return S_OK;
1731} // MDInternalRO::GetMethodDefProps
1732
1733//*****************************************************************************
1734// Given a scope and a methoddef/methodimpl, return RVA and impl flags
1735//*****************************************************************************
1736__checkReturn
1737HRESULT MDInternalRO::GetMethodImplProps(
1738 mdMethodDef tk, // [IN] MethodDef
1739 ULONG *pulCodeRVA, // [OUT] CodeRVA
1740 DWORD *pdwImplFlags) // [OUT] Impl. Flags
1741{
1742 HRESULT hr;
1743 _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
1744
1745 MethodRec *pMethodRec;
1746 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(RidFromToken(tk), &pMethodRec));
1747
1748 if (pulCodeRVA)
1749 {
1750 *pulCodeRVA = m_LiteWeightStgdb.m_MiniMd.getRVAOfMethod(pMethodRec);
1751 }
1752
1753 if (pdwImplFlags)
1754 {
1755 *pdwImplFlags = m_LiteWeightStgdb.m_MiniMd.getImplFlagsOfMethod(pMethodRec);
1756 }
1757
1758 return S_OK;
1759} // MDInternalRO::GetMethodImplProps
1760
1761
1762//*****************************************************************************
1763// return the field RVA
1764//*****************************************************************************
1765__checkReturn
1766HRESULT MDInternalRO::GetFieldRVA(
1767 mdToken fd, // [IN] FieldDef
1768 ULONG *pulCodeRVA) // [OUT] CodeRVA
1769{
1770 HRESULT hr;
1771 _ASSERTE(TypeFromToken(fd) == mdtFieldDef);
1772 _ASSERTE(pulCodeRVA);
1773
1774 RID iRecord;
1775 IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindFieldRVAFor(RidFromToken(fd), &iRecord));
1776
1777 if (InvalidRid(iRecord))
1778 {
1779 if (pulCodeRVA)
1780 *pulCodeRVA = 0;
1781 return CLDB_E_RECORD_NOTFOUND;
1782 }
1783
1784 FieldRVARec *pFieldRVARec;
1785 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRVARecord(iRecord, &pFieldRVARec));
1786
1787 *pulCodeRVA = m_LiteWeightStgdb.m_MiniMd.getRVAOfFieldRVA(pFieldRVARec);
1788 return NOERROR;
1789}
1790
1791//*****************************************************************************
1792// Given a fielddef, return the flags. Such as fdPublic, fdStatic, etc
1793//*****************************************************************************
1794__checkReturn
1795HRESULT
1796MDInternalRO::GetFieldDefProps(
1797 mdFieldDef fd, // given memberdef
1798 DWORD *pdwFlags) // [OUT] return fdPublic, fdPrive, etc flags
1799{
1800 HRESULT hr;
1801 _ASSERTE(TypeFromToken(fd) == mdtFieldDef);
1802
1803 FieldRec *pFieldRec;
1804
1805 *pdwFlags = (DWORD)-1;
1806 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec));
1807 *pdwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfField(pFieldRec);
1808
1809 return S_OK;
1810} // MDInternalRO::GetFieldDefProps
1811
1812//*****************************************************************************
1813// return default value of a token(could be paramdef, fielddef, or property)
1814//*****************************************************************************
1815__checkReturn
1816HRESULT MDInternalRO::GetDefaultValue( // return hresult
1817 mdToken tk, // [IN] given FieldDef, ParamDef, or Property
1818 MDDefaultValue *pMDDefaultValue) // [OUT] default value
1819{
1820 _ASSERTE(pMDDefaultValue);
1821
1822 HRESULT hr;
1823 BYTE bType;
1824 const VOID *pValue;
1825 ULONG cbValue;
1826 RID rid;
1827 IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindConstantFor(RidFromToken(tk), TypeFromToken(tk), &rid));
1828 if (InvalidRid(rid))
1829 {
1830 pMDDefaultValue->m_bType = ELEMENT_TYPE_VOID;
1831 return S_OK;
1832 }
1833 ConstantRec *pConstantRec;
1834 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetConstantRecord(rid, &pConstantRec));
1835
1836 // get the type of constant value
1837 bType = m_LiteWeightStgdb.m_MiniMd.getTypeOfConstant(pConstantRec);
1838
1839 // get the value blob
1840 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getValueOfConstant(pConstantRec, reinterpret_cast<const BYTE **>(&pValue), &cbValue));
1841 // convert it to our internal default value representation
1842 hr = _FillMDDefaultValue(bType, pValue, cbValue, pMDDefaultValue);
1843 return hr;
1844} // MDInternalRO::GetDefaultValue
1845
1846//*****************************************************************************
1847// Given a scope and a methoddef/fielddef, return the dispid
1848//*****************************************************************************
1849__checkReturn
1850HRESULT MDInternalRO::GetDispIdOfMemberDef( // return hresult
1851 mdToken tk, // given methoddef or fielddef
1852 ULONG *pDispid) // Put the dispid here.
1853{
1854#ifdef FEATURE_COMINTEROP
1855 HRESULT hr; // A result.
1856 const BYTE *pBlob; // Blob with dispid.
1857 ULONG cbBlob; // Length of blob.
1858 UINT32 dispid; // temporary for dispid.
1859
1860 // Get the DISPID, if any.
1861 _ASSERTE(pDispid);
1862
1863 *pDispid = DISPID_UNKNOWN;
1864 hr = GetCustomAttributeByName(tk, INTEROP_DISPID_TYPE, (const void**)&pBlob, &cbBlob);
1865 if (hr == S_OK)
1866 {
1867 CustomAttributeParser cap(pBlob, cbBlob);
1868 IfFailGo(cap.SkipProlog());
1869 IfFailGo(cap.GetU4(&dispid));
1870 *pDispid = dispid;
1871 }
1872
1873ErrExit:
1874 return hr;
1875#else // FEATURE_COMINTEROP
1876 _ASSERTE(false);
1877 return E_NOTIMPL;
1878#endif // FEATURE_COMINTEROP
1879} // MDInternalRO::GetDispIdOfMemberDef
1880
1881//*****************************************************************************
1882// Given interfaceimpl, return the TypeRef/TypeDef and flags
1883//*****************************************************************************
1884__checkReturn
1885HRESULT
1886MDInternalRO::GetTypeOfInterfaceImpl( // return hresult
1887 mdInterfaceImpl iiImpl, // given a interfaceimpl
1888 mdToken *ptkType)
1889{
1890 HRESULT hr;
1891 _ASSERTE(TypeFromToken(iiImpl) == mdtInterfaceImpl);
1892
1893 *ptkType = mdTypeDefNil;
1894
1895 InterfaceImplRec *pIIRec;
1896 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetInterfaceImplRecord(RidFromToken(iiImpl), &pIIRec));
1897 *ptkType = m_LiteWeightStgdb.m_MiniMd.getInterfaceOfInterfaceImpl(pIIRec);
1898 return S_OK;
1899} // MDInternalRO::GetTypeOfInterfaceImpl
1900
1901//*****************************************************************************
1902// This routine gets the properties for the given MethodSpec token.
1903//*****************************************************************************
1904__checkReturn
1905HRESULT MDInternalRO::GetMethodSpecProps( // S_OK or error.
1906 mdMethodSpec mi, // [IN] The method instantiation
1907 mdToken *tkParent, // [OUT] MethodDef or MemberRef
1908 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
1909 ULONG *pcbSigBlob) // [OUT] actual size of signature blob
1910{
1911 HRESULT hr = NOERROR;
1912 MethodSpecRec *pMethodSpecRec;
1913
1914 LOG((LOGMD, "MD RegMeta::GetMethodSpecProps(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1915 mi, tkParent, ppvSigBlob, pcbSigBlob));
1916
1917 _ASSERTE(TypeFromToken(mi) == mdtMethodSpec);
1918
1919 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSpecRecord(RidFromToken(mi), &pMethodSpecRec));
1920
1921 if (tkParent)
1922 *tkParent = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSpec(pMethodSpecRec);
1923
1924 if (ppvSigBlob || pcbSigBlob)
1925 {
1926 // caller wants signature information
1927 PCCOR_SIGNATURE pvSigTmp;
1928 ULONG cbSig;
1929 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getInstantiationOfMethodSpec(pMethodSpecRec, &pvSigTmp, &cbSig));
1930 if ( ppvSigBlob )
1931 *ppvSigBlob = pvSigTmp;
1932 if ( pcbSigBlob)
1933 *pcbSigBlob = cbSig;
1934 }
1935
1936
1937 return hr;
1938} // MDInternalRO::GetMethodSpecProps
1939
1940
1941
1942//*****************************************************************************
1943// Given a classname, return the typedef
1944//*****************************************************************************
1945__checkReturn
1946HRESULT
1947MDInternalRO::FindTypeDef(
1948 LPCSTR szTypeDefNamespace, // [IN] Namespace for the TypeDef.
1949 LPCSTR szTypeDefName, // [IN] Name of the TypeDef.
1950 mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef of enclosing class.
1951 mdTypeDef * ptkTypeDef) // [OUT] return typedef
1952{
1953 HRESULT hr = S_OK;
1954
1955 _ASSERTE((szTypeDefName != NULL) && (ptkTypeDef != NULL));
1956 _ASSERTE((TypeFromToken(tkEnclosingClass) == mdtTypeRef) ||
1957 (TypeFromToken(tkEnclosingClass) == mdtTypeDef) ||
1958 IsNilToken(tkEnclosingClass));
1959
1960 // initialize the output parameter
1961 *ptkTypeDef = mdTypeDefNil;
1962
1963 // Treat no namespace as empty string.
1964 if (szTypeDefNamespace == NULL)
1965 szTypeDefNamespace = "";
1966
1967 // Do a linear search
1968 ULONG cTypeDefRecs = m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs();
1969 TypeDefRec * pTypeDefRec;
1970 LPCUTF8 szName;
1971 LPCUTF8 szNamespace;
1972 DWORD dwFlags;
1973
1974 // Get TypeDef of the tkEnclosingClass passed in
1975 if (TypeFromToken(tkEnclosingClass) == mdtTypeRef)
1976 {
1977 TypeRefRec * pTypeRefRec;
1978 mdToken tkResolutionScope;
1979
1980 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeRefRecord(RidFromToken(tkEnclosingClass), &pTypeRefRec));
1981 tkResolutionScope = m_LiteWeightStgdb.m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec);
1982 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, &szNamespace));
1983 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeRef(pTypeRefRec, &szName));
1984
1985 // Update tkEnclosingClass to TypeDef
1986 IfFailRet(FindTypeDef(
1987 szNamespace,
1988 szName,
1989 (TypeFromToken(tkResolutionScope) == mdtTypeRef) ? tkResolutionScope : mdTokenNil,
1990 &tkEnclosingClass));
1991 _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef);
1992 }
1993
1994 // Search for the TypeDef
1995 for (ULONG i = 1; i <= cTypeDefRecs; i++)
1996 {
1997 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(i, &pTypeDefRec));
1998
1999 dwFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfTypeDef(pTypeDefRec);
2000
2001 if (!IsTdNested(dwFlags) && !IsNilToken(tkEnclosingClass))
2002 {
2003 // If the class is not Nested and EnclosingClass passed in is not nil
2004 continue;
2005 }
2006 else if (IsTdNested(dwFlags) && IsNilToken(tkEnclosingClass))
2007 {
2008 // If the class is nested and EnclosingClass passed is nil
2009 continue;
2010 }
2011 else if (!IsNilToken(tkEnclosingClass))
2012 {
2013 _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef);
2014
2015 RID iNestedClassRec;
2016 NestedClassRec * pNestedClassRec;
2017 mdTypeDef tkEnclosingClassTmp;
2018
2019 IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindNestedClassFor(i, &iNestedClassRec));
2020 if (InvalidRid(iNestedClassRec))
2021 continue;
2022 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetNestedClassRecord(iNestedClassRec, &pNestedClassRec));
2023 tkEnclosingClassTmp = m_LiteWeightStgdb.m_MiniMd.getEnclosingClassOfNestedClass(pNestedClassRec);
2024 if (tkEnclosingClass != tkEnclosingClassTmp)
2025 continue;
2026 }
2027
2028 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfTypeDef(pTypeDefRec, &szName));
2029 if (strcmp(szTypeDefName, szName) == 0)
2030 {
2031 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNamespaceOfTypeDef(pTypeDefRec, &szNamespace));
2032 if (strcmp(szTypeDefNamespace, szNamespace) == 0)
2033 {
2034 *ptkTypeDef = TokenFromRid(i, mdtTypeDef);
2035 return S_OK;
2036 }
2037 }
2038 }
2039 // Cannot find the TypeDef by name
2040 return CLDB_E_RECORD_NOTFOUND;
2041} // MDInternalRO::FindTypeDef
2042
2043//*****************************************************************************
2044// Given a memberref, return a pointer to memberref's name and signature
2045//*****************************************************************************
2046// Warning: Even when the return value is ok, *ppvSigBlob could be NULL if
2047// the metadata is corrupted! (e.g. if CPackedLen::GetLength returned -1).
2048// TODO: consider returning a HRESULT to make errors evident to the caller.
2049//*****************************************************************************
2050__checkReturn
2051HRESULT
2052MDInternalRO::GetNameAndSigOfMemberRef( // meberref's name
2053 mdMemberRef memberref, // given a memberref
2054 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature
2055 ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
2056 LPCSTR *pszMemberRefName)
2057{
2058 _ASSERTE(TypeFromToken(memberref) == mdtMemberRef);
2059
2060 HRESULT hr;
2061 MemberRefRec *pMemberRefRec;
2062 *pszMemberRefName = NULL;
2063 if (ppvSigBlob != NULL)
2064 {
2065 _ASSERTE(pcbSigBlob != NULL);
2066 *ppvSigBlob = NULL;
2067 *pcbSigBlob = 0;
2068 }
2069 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec));
2070 if (ppvSigBlob != NULL)
2071 {
2072 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfMemberRef(pMemberRefRec, ppvSigBlob, pcbSigBlob));
2073 }
2074 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfMemberRef(pMemberRefRec, pszMemberRefName));
2075 return S_OK;
2076} // MDInternalRO::GetNameAndSigOfMemberRef
2077
2078//*****************************************************************************
2079// Given a memberref, return parent token. It can be a TypeRef, ModuleRef, or a MethodDef
2080//*****************************************************************************
2081__checkReturn
2082HRESULT
2083MDInternalRO::GetParentOfMemberRef(
2084 mdMemberRef memberref, // given a typedef
2085 mdToken *ptkParent) // return the parent token
2086{
2087 HRESULT hr;
2088 _ASSERTE(TypeFromToken(memberref) == mdtMemberRef);
2089
2090 MemberRefRec *pMemberRefRec;
2091
2092 *ptkParent = mdTokenNil;
2093 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec));
2094 *ptkParent = m_LiteWeightStgdb.m_MiniMd.getClassOfMemberRef(pMemberRefRec);
2095
2096 return S_OK;
2097} // MDInternalRO::GetParentOfMemberRef
2098
2099//*****************************************************************************
2100// return properties of a paramdef
2101//*****************************************************************************/
2102__checkReturn
2103HRESULT
2104MDInternalRO::GetParamDefProps (
2105 mdParamDef paramdef, // given a paramdef
2106 USHORT *pusSequence, // [OUT] slot number for this parameter
2107 DWORD *pdwAttr, // [OUT] flags
2108 LPCSTR *pszName) // [OUT] return the name of the parameter
2109{
2110 _ASSERTE(TypeFromToken(paramdef) == mdtParamDef);
2111 HRESULT hr;
2112 ParamRec *pParamRec;
2113
2114 *pszName = NULL;
2115 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetParamRecord(RidFromToken(paramdef), &pParamRec));
2116 if (pdwAttr != NULL)
2117 {
2118 *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfParam(pParamRec);
2119 }
2120 if (pusSequence != NULL)
2121 {
2122 *pusSequence = m_LiteWeightStgdb.m_MiniMd.getSequenceOfParam(pParamRec);
2123 }
2124 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfParam(pParamRec, pszName));
2125
2126 return S_OK;
2127} // MDInternalRO::GetParamDefProps
2128
2129//*****************************************************************************
2130// Get property info for the method.
2131//*****************************************************************************
2132int MDInternalRO::CMethodSemanticsMapSearcher::Compare(
2133 const CMethodSemanticsMap *psFirst,
2134 const CMethodSemanticsMap *psSecond)
2135{
2136 if (psFirst->m_mdMethod < psSecond->m_mdMethod)
2137 return -1;
2138 if (psFirst->m_mdMethod > psSecond->m_mdMethod)
2139 return 1;
2140 return 0;
2141} // MDInternalRO::CMethodSemanticsMapSearcher::Compare
2142
2143#ifndef DACCESS_COMPILE
2144int MDInternalRO::CMethodSemanticsMapSorter::Compare(
2145 CMethodSemanticsMap *psFirst,
2146 CMethodSemanticsMap *psSecond)
2147{
2148 if (psFirst->m_mdMethod < psSecond->m_mdMethod)
2149 return -1;
2150 if (psFirst->m_mdMethod > psSecond->m_mdMethod)
2151 return 1;
2152 return 0;
2153} // MDInternalRO::CMethodSemanticsMapSorter::Compare
2154
2155__checkReturn
2156HRESULT MDInternalRO::GetPropertyInfoForMethodDef( // Result.
2157 mdMethodDef md, // [IN] memberdef
2158 mdProperty *ppd, // [OUT] put property token here
2159 LPCSTR *pName, // [OUT] put pointer to name here
2160 ULONG *pSemantic) // [OUT] put semantic here
2161{
2162 HRESULT hr;
2163 MethodSemanticsRec *pSemantics; // A MethodSemantics record.
2164 MethodSemanticsRec *pFound=0; // A MethodSemantics record that is a property for the desired function.
2165 RID ridCur; // loop control.
2166 RID ridMax; // Count of entries in table.
2167 USHORT usSemantics = 0; // A method's semantics.
2168 mdToken tk; // A method def.
2169
2170 ridMax = m_LiteWeightStgdb.m_MiniMd.getCountMethodSemantics();
2171
2172 // Lazy initialization of m_pMethodSemanticsMap
2173 if ((ridMax > 10) && (m_pMethodSemanticsMap == NULL))
2174 {
2175 NewHolder<CMethodSemanticsMap> pMethodSemanticsMap = new (nothrow) CMethodSemanticsMap[ridMax];
2176 if (pMethodSemanticsMap != NULL)
2177 {
2178 // Fill the table in MethodSemantics order.
2179 for (ridCur = 1; ridCur <= ridMax; ridCur++)
2180 {
2181 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
2182 tk = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics);
2183 pMethodSemanticsMap[ridCur-1].m_mdMethod = tk;
2184 pMethodSemanticsMap[ridCur-1].m_ridSemantics = ridCur;
2185 }
2186 // Sort to MethodDef order.
2187 CMethodSemanticsMapSorter sorter(pMethodSemanticsMap, ridMax);
2188 sorter.Sort();
2189
2190 if (InterlockedCompareExchangeT<CMethodSemanticsMap *>(
2191 &m_pMethodSemanticsMap, pMethodSemanticsMap, NULL) == NULL)
2192 { // The exchange did happen, supress of the allocated map
2193 pMethodSemanticsMap.SuppressRelease();
2194 }
2195 }
2196 }
2197
2198 // Use m_pMethodSemanticsMap if it has been built.
2199 if (m_pMethodSemanticsMap != NULL)
2200 {
2201 CMethodSemanticsMapSearcher searcher(m_pMethodSemanticsMap, ridMax);
2202 CMethodSemanticsMap target;
2203 const CMethodSemanticsMap * pMatchedMethod;
2204 target.m_mdMethod = md;
2205 pMatchedMethod = searcher.Find(&target);
2206
2207 // Was there at least one match?
2208 if (pMatchedMethod != NULL)
2209 {
2210 _ASSERTE(pMatchedMethod >= m_pMethodSemanticsMap);
2211 _ASSERTE(pMatchedMethod < m_pMethodSemanticsMap+ridMax);
2212 _ASSERTE(pMatchedMethod->m_mdMethod == md);
2213
2214 ridCur = pMatchedMethod->m_ridSemantics;
2215 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
2216 usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
2217
2218 // If the semantics record is a getter or setter for the method, that's what we want.
2219 if (usSemantics == msGetter || usSemantics == msSetter)
2220 pFound = pSemantics;
2221 else
2222 { // The semantics record was neither getter or setter. Because there can be
2223 // multiple semantics records for a given method, look for other semantics
2224 // records that match this record.
2225 const CMethodSemanticsMap *pScan;
2226 const CMethodSemanticsMap *pLo=m_pMethodSemanticsMap;
2227 const CMethodSemanticsMap *pHi=pLo+ridMax-1;
2228 for (pScan = pMatchedMethod-1; pScan >= pLo; --pScan)
2229 {
2230 if (pScan->m_mdMethod == md)
2231 {
2232 ridCur = pScan->m_ridSemantics;
2233 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
2234 usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
2235
2236 if (usSemantics == msGetter || usSemantics == msSetter)
2237 {
2238 pFound = pSemantics;
2239 break;
2240 }
2241 }
2242 else
2243 break;
2244 }
2245
2246 if (pFound == 0)
2247 { // Not found looking down, try looking up.
2248 for (pScan = pMatchedMethod+1; pScan <= pHi; ++pScan)
2249 {
2250 if (pScan->m_mdMethod == md)
2251 {
2252 ridCur = pScan->m_ridSemantics;
2253 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
2254 usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
2255
2256 if (usSemantics == msGetter || usSemantics == msSetter)
2257 {
2258 pFound = pSemantics;
2259 break;
2260 }
2261 }
2262 else
2263 break;
2264 }
2265
2266 }
2267 }
2268 }
2269 }
2270 else
2271 { // Scan entire table.
2272 for (ridCur = 1; ridCur <= ridMax; ridCur++)
2273 {
2274 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
2275 if (md == m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics))
2276 { // The method matched, is this a property?
2277 usSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
2278 if (usSemantics == msGetter || usSemantics == msSetter)
2279 { // found a match.
2280 pFound = pSemantics;
2281 break;
2282 }
2283 }
2284 }
2285 }
2286
2287 // Did the search find anything?
2288 if (pFound)
2289 { // found a match. Fill out the output parameters
2290 PropertyRec *pProperty;
2291 mdProperty prop;
2292 prop = m_LiteWeightStgdb.m_MiniMd.getAssociationOfMethodSemantics(pFound);
2293
2294 if (ppd)
2295 *ppd = prop;
2296 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(RidFromToken(prop), &pProperty));
2297
2298 if (pName != NULL)
2299 {
2300 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, pName));
2301 }
2302
2303 if (pSemantic)
2304 *pSemantic = usSemantics;
2305 return S_OK;
2306 }
2307 return S_FALSE;
2308} // MDInternalRO::GetPropertyInfoForMethodDef
2309#endif //!DACCESS_COMPILE
2310
2311//*****************************************************************************
2312// return the pack size of a class
2313//*****************************************************************************
2314__checkReturn
2315HRESULT MDInternalRO::GetClassPackSize(
2316 mdTypeDef td, // [IN] give typedef
2317 DWORD *pdwPackSize) // [OUT]
2318{
2319 HRESULT hr = NOERROR;
2320
2321 _ASSERTE(TypeFromToken(td) == mdtTypeDef && pdwPackSize);
2322
2323 ClassLayoutRec *pRec;
2324 RID ridClassLayout;
2325
2326 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindClassLayoutFor(RidFromToken(td), &ridClassLayout));
2327 if (InvalidRid(ridClassLayout))
2328 {
2329 hr = CLDB_E_RECORD_NOTFOUND;
2330 goto ErrExit;
2331 }
2332
2333 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec));
2334 *pdwPackSize = m_LiteWeightStgdb.m_MiniMd.getPackingSizeOfClassLayout(pRec);
2335ErrExit:
2336 return hr;
2337} // MDInternalRO::GetClassPackSize
2338
2339
2340//*****************************************************************************
2341// return the total size of a value class
2342//*****************************************************************************
2343__checkReturn
2344HRESULT MDInternalRO::GetClassTotalSize( // return error if a class does not have total size info
2345 mdTypeDef td, // [IN] give typedef
2346 ULONG *pulClassSize) // [OUT] return the total size of the class
2347{
2348 _ASSERTE(TypeFromToken(td) == mdtTypeDef && pulClassSize);
2349
2350 ClassLayoutRec *pRec;
2351 HRESULT hr = NOERROR;
2352 RID ridClassLayout;
2353
2354 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindClassLayoutFor(RidFromToken(td), &ridClassLayout));
2355 if (InvalidRid(ridClassLayout))
2356 {
2357 hr = CLDB_E_RECORD_NOTFOUND;
2358 goto ErrExit;
2359 }
2360
2361 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec));
2362 *pulClassSize = m_LiteWeightStgdb.m_MiniMd.getClassSizeOfClassLayout(pRec);
2363ErrExit:
2364 return hr;
2365} // MDInternalRO::GetClassTotalSize
2366
2367
2368//*****************************************************************************
2369// init the layout enumerator of a class
2370//*****************************************************************************
2371__checkReturn
2372HRESULT MDInternalRO::GetClassLayoutInit(
2373 mdTypeDef td, // [IN] give typedef
2374 MD_CLASS_LAYOUT *pmdLayout) // [OUT] set up the status of query here
2375{
2376 HRESULT hr = NOERROR;
2377 _ASSERTE(TypeFromToken(td) == mdtTypeDef);
2378
2379 // initialize the output parameter
2380 _ASSERTE(pmdLayout);
2381 memset(pmdLayout, 0, sizeof(MD_CLASS_LAYOUT));
2382
2383 TypeDefRec *pTypeDefRec;
2384
2385 // record for this typedef in TypeDef Table
2386 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec));
2387
2388 // find the starting and end field for this typedef
2389 pmdLayout->m_ridFieldCur = m_LiteWeightStgdb.m_MiniMd.getFieldListOfTypeDef(pTypeDefRec);
2390 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(td), &(pmdLayout->m_ridFieldEnd)));
2391 return hr;
2392} // MDInternalRO::GetClassLayoutInit
2393
2394
2395//*****************************************************************************
2396// return the field offset for a given field
2397//*****************************************************************************
2398__checkReturn
2399HRESULT MDInternalRO::GetFieldOffset(
2400 mdFieldDef fd, // [IN] fielddef
2401 ULONG *pulOffset) // [OUT] FieldOffset
2402{
2403 HRESULT hr = S_OK;
2404 FieldLayoutRec *pRec;
2405
2406 _ASSERTE(pulOffset);
2407
2408 RID iLayout;
2409
2410 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldLayoutFor(RidFromToken(fd), &iLayout));
2411
2412 if (InvalidRid(iLayout))
2413 {
2414 hr = S_FALSE;
2415 goto ErrExit;
2416 }
2417
2418 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldLayoutRecord(iLayout, &pRec));
2419 *pulOffset = m_LiteWeightStgdb.m_MiniMd.getOffSetOfFieldLayout(pRec);
2420 _ASSERTE(*pulOffset != ULONG_MAX);
2421
2422ErrExit:
2423 return hr;
2424}
2425
2426
2427//*****************************************************************************
2428// enum the next the field layout
2429//*****************************************************************************
2430__checkReturn
2431HRESULT MDInternalRO::GetClassLayoutNext(
2432 MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here
2433 mdFieldDef *pfd, // [OUT] field def
2434 ULONG *pulOffset) // [OUT] field offset or sequence
2435{
2436 HRESULT hr = S_OK;
2437
2438 _ASSERTE(pfd && pulOffset && pLayout);
2439
2440 RID iLayout2;
2441 FieldLayoutRec *pRec;
2442
2443 // Make sure no one is messing with pLayout->m_ridFieldLayoutCur, since this doesn't
2444 // mean anything if we are using FieldLayout table.
2445 while (pLayout->m_ridFieldCur < pLayout->m_ridFieldEnd)
2446 {
2447 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldLayoutFor(pLayout->m_ridFieldCur, &iLayout2));
2448 pLayout->m_ridFieldCur++;
2449 if (!InvalidRid(iLayout2))
2450 {
2451 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldLayoutRecord(iLayout2, &pRec));
2452 *pulOffset = m_LiteWeightStgdb.m_MiniMd.getOffSetOfFieldLayout(pRec);
2453 _ASSERTE(*pulOffset != ULONG_MAX);
2454 *pfd = TokenFromRid(pLayout->m_ridFieldCur - 1, mdtFieldDef);
2455 goto ErrExit;
2456 }
2457 }
2458
2459 *pfd = mdFieldDefNil;
2460 hr = S_FALSE;
2461
2462 // fall through
2463
2464ErrExit:
2465 return hr;
2466} // MDInternalRO::GetClassLayoutNext
2467
2468
2469//*****************************************************************************
2470// return the field's native type signature
2471//*****************************************************************************
2472__checkReturn
2473HRESULT MDInternalRO::GetFieldMarshal( // return error if no native type associate with the token
2474 mdToken tk, // [IN] given fielddef or paramdef
2475 PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature
2476 ULONG *pcbNativeType) // [OUT] the count of bytes of *ppvNativeType
2477{
2478 // output parameters have to be supplied
2479 _ASSERTE(pcbNativeType);
2480
2481 RID rid;
2482 FieldMarshalRec *pFieldMarshalRec;
2483 HRESULT hr = NOERROR;
2484
2485 // find the row containing the marshal definition for tk
2486 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindFieldMarshalFor(RidFromToken(tk), TypeFromToken(tk), &rid));
2487 if (InvalidRid(rid))
2488 {
2489 *pSigNativeType = NULL;
2490 *pcbNativeType = 0;
2491 hr = CLDB_E_RECORD_NOTFOUND;
2492 goto ErrExit;
2493 }
2494 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldMarshalRecord(rid, &pFieldMarshalRec));
2495
2496 // get the native type
2497 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNativeTypeOfFieldMarshal(pFieldMarshalRec, pSigNativeType, pcbNativeType));
2498ErrExit:
2499 return hr;
2500} // MDInternalRO::GetFieldMarshal
2501
2502
2503
2504//*****************************************
2505// property APIs
2506//*****************************************
2507
2508//*****************************************************************************
2509// Find property by name
2510//*****************************************************************************
2511__checkReturn
2512HRESULT MDInternalRO::FindProperty(
2513 mdTypeDef td, // [IN] given a typdef
2514 LPCSTR szPropName, // [IN] property name
2515 mdProperty *pProp) // [OUT] return property token
2516{
2517 HRESULT hr = NOERROR;
2518
2519 // output parameters have to be supplied
2520 _ASSERTE(TypeFromToken(td) == mdtTypeDef && pProp);
2521
2522 PropertyMapRec *pRec;
2523 PropertyRec *pProperty;
2524 RID ridPropertyMap;
2525 RID ridCur;
2526 RID ridEnd;
2527 LPCUTF8 szName;
2528
2529 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindPropertyMapFor(RidFromToken(td), &ridPropertyMap));
2530 if (InvalidRid(ridPropertyMap))
2531 {
2532 // not found!
2533 hr = CLDB_E_RECORD_NOTFOUND;
2534 goto ErrExit;
2535 }
2536
2537 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pRec));
2538
2539 // get the starting/ending rid of properties of this typedef
2540 ridCur = m_LiteWeightStgdb.m_MiniMd.getPropertyListOfPropertyMap(pRec);
2541 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndPropertyListOfPropertyMap(ridPropertyMap, &ridEnd));
2542
2543 for (; ridCur < ridEnd; ridCur ++)
2544 {
2545 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(ridCur, &pProperty));
2546 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, &szName));
2547 if (strcmp(szName, szPropName) ==0)
2548 {
2549 // Found the match. Set the output parameter and we are done.
2550 *pProp = TokenFromRid(ridCur, mdtProperty);
2551 goto ErrExit;
2552 }
2553 }
2554
2555 // not found
2556 hr = CLDB_E_RECORD_NOTFOUND;
2557ErrExit:
2558 return hr;
2559
2560} // MDInternalRO::FindProperty
2561
2562
2563
2564//*****************************************************************************
2565// return the properties of a property
2566//*****************************************************************************
2567__checkReturn
2568HRESULT MDInternalRO::GetPropertyProps(
2569 mdProperty prop, // [IN] property token
2570 LPCSTR *pszProperty, // [OUT] property name
2571 DWORD *pdwPropFlags, // [OUT] property flags.
2572 PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob
2573 ULONG *pcbSig) // [OUT] count of bytes in *ppvSig
2574{
2575 // output parameters have to be supplied
2576 _ASSERTE(TypeFromToken(prop) == mdtProperty);
2577
2578 HRESULT hr;
2579
2580 PropertyRec *pProperty;
2581 ULONG cbSig;
2582
2583 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetPropertyRecord(RidFromToken(prop), &pProperty));
2584
2585 // get name of the property
2586 if (pszProperty != NULL)
2587 {
2588 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfProperty(pProperty, pszProperty));
2589 }
2590
2591 // get the flags of property
2592 if (pdwPropFlags)
2593 *pdwPropFlags = m_LiteWeightStgdb.m_MiniMd.getPropFlagsOfProperty(pProperty);
2594
2595 // get the type of the property
2596 if (ppvSig != NULL)
2597 {
2598 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeOfProperty(pProperty, ppvSig, &cbSig));
2599 if (pcbSig != NULL)
2600 {
2601 *pcbSig = cbSig;
2602 }
2603 }
2604
2605 return S_OK;
2606} // MDInternalRO::GetPropertyProps
2607
2608
2609//**********************************
2610//
2611// Event APIs
2612//
2613//**********************************
2614
2615//*****************************************************************************
2616// return an event by given the name
2617//*****************************************************************************
2618__checkReturn
2619HRESULT MDInternalRO::FindEvent(
2620 mdTypeDef td, // [IN] given a typdef
2621 LPCSTR szEventName, // [IN] event name
2622 mdEvent *pEvent) // [OUT] return event token
2623{
2624 HRESULT hr = NOERROR;
2625
2626 // output parameters have to be supplied
2627 _ASSERTE(TypeFromToken(td) == mdtTypeDef && pEvent);
2628
2629 EventMapRec *pRec;
2630 EventRec *pEventRec;
2631 RID ridEventMap;
2632 RID ridCur;
2633 RID ridEnd;
2634 LPCUTF8 szName;
2635
2636 IfFailGo(m_LiteWeightStgdb.m_MiniMd.FindEventMapFor(RidFromToken(td), &ridEventMap));
2637 if (InvalidRid(ridEventMap))
2638 {
2639 // not found!
2640 hr = CLDB_E_RECORD_NOTFOUND;
2641 goto ErrExit;
2642 }
2643 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventMapRecord(ridEventMap, &pRec));
2644
2645 // get the starting/ending rid of properties of this typedef
2646 ridCur = m_LiteWeightStgdb.m_MiniMd.getEventListOfEventMap(pRec);
2647 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getEndEventListOfEventMap(ridEventMap, &ridEnd));
2648
2649 for (; ridCur < ridEnd; ridCur ++)
2650 {
2651 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetEventRecord(ridCur, &pEventRec));
2652 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfEvent(pEventRec, &szName));
2653 if (strcmp(szName, szEventName) ==0)
2654 {
2655 // Found the match. Set the output parameter and we are done.
2656 *pEvent = TokenFromRid(ridCur, mdtEvent);
2657 goto ErrExit;
2658 }
2659 }
2660
2661 // not found
2662 hr = CLDB_E_RECORD_NOTFOUND;
2663ErrExit:
2664 return hr;
2665} // MDInternalRO::FindEvent
2666
2667
2668//*****************************************************************************
2669// return the properties of an event
2670//*****************************************************************************
2671__checkReturn
2672HRESULT MDInternalRO::GetEventProps( // S_OK, S_FALSE, or error.
2673 mdEvent ev, // [IN] event token
2674 LPCSTR *pszEvent, // [OUT] Event name
2675 DWORD *pdwEventFlags, // [OUT] Event flags.
2676 mdToken *ptkEventType) // [OUT] EventType class
2677{
2678 // output parameters have to be supplied
2679 _ASSERTE(TypeFromToken(ev) == mdtEvent);
2680
2681 HRESULT hr;
2682 EventRec *pEvent;
2683
2684 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetEventRecord(RidFromToken(ev), &pEvent));
2685 if (pszEvent != NULL)
2686 {
2687 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfEvent(pEvent, pszEvent));
2688 }
2689 if (pdwEventFlags)
2690 *pdwEventFlags = m_LiteWeightStgdb.m_MiniMd.getEventFlagsOfEvent(pEvent);
2691 if (ptkEventType)
2692 *ptkEventType = m_LiteWeightStgdb.m_MiniMd.getEventTypeOfEvent(pEvent);
2693
2694 return S_OK;
2695} // MDInternalRO::GetEventProps
2696
2697//*****************************************************************************
2698// return the properties of a generic param
2699//*****************************************************************************
2700__checkReturn
2701HRESULT MDInternalRO::GetGenericParamProps( // S_OK or error.
2702 mdGenericParam rd, // [IN] The type parameter
2703 ULONG* pulSequence, // [OUT] Parameter sequence number
2704 DWORD* pdwAttr, // [OUT] Type parameter flags (for future use)
2705 mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef)
2706 DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use)
2707 LPCSTR *szName) // [OUT] The name
2708{
2709 HRESULT hr = NOERROR;
2710 GenericParamRec * pGenericParamRec = NULL;
2711
2712 // See if this version of the metadata can do Generics
2713 if (!m_LiteWeightStgdb.m_MiniMd.SupportsGenerics())
2714 IfFailGo(CLDB_E_INCOMPATIBLE);
2715
2716 _ASSERTE(TypeFromToken(rd) == mdtGenericParam);
2717 if (TypeFromToken(rd) != mdtGenericParam)
2718 {
2719 IfFailGo(CLDB_E_FILE_CORRUPT);
2720 }
2721
2722 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetGenericParamRecord(RidFromToken(rd), &pGenericParamRec));
2723
2724 if (pulSequence)
2725 *pulSequence = m_LiteWeightStgdb.m_MiniMd.getNumberOfGenericParam(pGenericParamRec);
2726 if (pdwAttr)
2727 *pdwAttr = m_LiteWeightStgdb.m_MiniMd.getFlagsOfGenericParam(pGenericParamRec);
2728 if (ptOwner)
2729 *ptOwner = m_LiteWeightStgdb.m_MiniMd.getOwnerOfGenericParam(pGenericParamRec);
2730 if (szName != NULL)
2731 {
2732 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getNameOfGenericParam(pGenericParamRec, szName));
2733 }
2734ErrExit:
2735 return hr;
2736} // MDInternalRO::GetGenericParamProps
2737
2738//*****************************************************************************
2739// This routine gets the properties for the given GenericParamConstraint token.
2740//*****************************************************************************
2741__checkReturn
2742HRESULT MDInternalRO::GetGenericParamConstraintProps( // S_OK or error.
2743 mdGenericParamConstraint rd, // [IN] The constraint token
2744 mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained
2745 mdToken *ptkConstraintType) // [OUT] TypeDef/Ref/Spec constraint
2746{
2747 HRESULT hr = NOERROR;
2748 GenericParamConstraintRec *pGPCRec;
2749 RID ridRD = RidFromToken(rd);
2750
2751 // See if this version of the metadata can do Generics
2752 if (!m_LiteWeightStgdb.m_MiniMd.SupportsGenerics())
2753 IfFailGo(CLDB_E_INCOMPATIBLE);
2754
2755 if((TypeFromToken(rd) == mdtGenericParamConstraint) && (ridRD != 0))
2756 {
2757 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetGenericParamConstraintRecord(ridRD, &pGPCRec));
2758
2759 if (ptGenericParam)
2760 *ptGenericParam = TokenFromRid(m_LiteWeightStgdb.m_MiniMd.getOwnerOfGenericParamConstraint(pGPCRec),mdtGenericParam);
2761 if (ptkConstraintType)
2762 *ptkConstraintType = m_LiteWeightStgdb.m_MiniMd.getConstraintOfGenericParamConstraint(pGPCRec);
2763 }
2764 else
2765 hr = META_E_BAD_INPUT_PARAMETER;
2766
2767ErrExit:
2768 return hr;
2769} // MDInternalRO::GetGenericParamConstraintProps
2770
2771//*****************************************************************************
2772// Find methoddef of a particular associate with a property or an event
2773//*****************************************************************************
2774__checkReturn
2775HRESULT MDInternalRO::FindAssociate(
2776 mdToken evprop, // [IN] given a property or event token
2777 DWORD dwSemantics, // [IN] given a associate semantics(setter, getter, testdefault, reset)
2778 mdMethodDef *pmd) // [OUT] return method def token
2779{
2780 HRESULT hr = NOERROR;
2781
2782 // output parameters have to be supplied
2783 _ASSERTE(pmd);
2784 _ASSERTE(TypeFromToken(evprop) == mdtEvent || TypeFromToken(evprop) == mdtProperty);
2785
2786 MethodSemanticsRec *pSemantics;
2787 RID ridCur;
2788 RID ridEnd;
2789
2790 IfFailGo(m_LiteWeightStgdb.m_MiniMd.getAssociatesForToken(evprop, &ridEnd, &ridCur));
2791 for (; ridCur < ridEnd; ridCur++)
2792 {
2793 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
2794 if (dwSemantics == m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics))
2795 {
2796 // found a match
2797 *pmd = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics);
2798 goto ErrExit;
2799 }
2800 }
2801
2802 // not found
2803 hr = CLDB_E_RECORD_NOTFOUND;
2804ErrExit:
2805 return hr;
2806} // MDInternalRO::FindAssociate
2807
2808
2809//*****************************************************************************
2810// get counts of methodsemantics associated with a particular property/event
2811//*****************************************************************************
2812__checkReturn
2813HRESULT MDInternalRO::EnumAssociateInit(
2814 mdToken evprop, // [IN] given a property or an event token
2815 HENUMInternal *phEnum) // [OUT] cursor to hold the query result
2816{
2817 HRESULT hr;
2818 _ASSERTE(phEnum);
2819
2820 memset(phEnum, 0, sizeof(HENUMInternal));
2821
2822 // There is no token kind!!!
2823 phEnum->m_tkKind = ULONG_MAX;
2824
2825 // output parameters have to be supplied
2826 _ASSERTE(TypeFromToken(evprop) == mdtEvent || TypeFromToken(evprop) == mdtProperty);
2827
2828 phEnum->m_EnumType = MDSimpleEnum;
2829 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getAssociatesForToken(evprop, &phEnum->u.m_ulEnd, &phEnum->u.m_ulStart));
2830 phEnum->u.m_ulCur = phEnum->u.m_ulStart;
2831 phEnum->m_ulCount = phEnum->u.m_ulEnd - phEnum->u.m_ulStart;
2832
2833 return S_OK;
2834} // MDInternalRO::EnumAssociateInit
2835
2836
2837//*****************************************************************************
2838// get all methodsemantics associated with a particular property/event
2839//*****************************************************************************
2840__checkReturn
2841HRESULT MDInternalRO::GetAllAssociates(
2842 HENUMInternal *phEnum, // [OUT] cursor to hold the query result
2843 ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output
2844 ULONG cAssociateRec) // [IN] size of the buffer
2845{
2846 _ASSERTE(phEnum && pAssociateRec);
2847
2848 HRESULT hr;
2849 MethodSemanticsRec *pSemantics;
2850 RID ridCur;
2851 _ASSERTE(cAssociateRec == phEnum->m_ulCount);
2852
2853 // Convert from row pointers to RIDs.
2854 for (ridCur = phEnum->u.m_ulStart; ridCur < phEnum->u.m_ulEnd; ++ridCur)
2855 {
2856 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
2857
2858 pAssociateRec[ridCur-phEnum->u.m_ulStart].m_memberdef = m_LiteWeightStgdb.m_MiniMd.getMethodOfMethodSemantics(pSemantics);
2859 pAssociateRec[ridCur-phEnum->u.m_ulStart].m_dwSemantics = m_LiteWeightStgdb.m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
2860 }
2861
2862 return S_OK;
2863} // MDInternalRO::GetAllAssociates
2864
2865
2866//*****************************************************************************
2867// Get the Action and Permissions blob for a given PermissionSet.
2868//*****************************************************************************
2869__checkReturn
2870HRESULT MDInternalRO::GetPermissionSetProps(
2871 mdPermission pm, // [IN] the permission token.
2872 DWORD *pdwAction, // [OUT] CorDeclSecurity.
2873 void const **ppvPermission, // [OUT] permission blob.
2874 ULONG *pcbPermission) // [OUT] count of bytes of pvPermission.
2875{
2876 HRESULT hr;
2877 _ASSERTE(TypeFromToken(pm) == mdtPermission);
2878 _ASSERTE(pdwAction && ppvPermission && pcbPermission);
2879
2880 DeclSecurityRec *pPerm;
2881
2882 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetDeclSecurityRecord(RidFromToken(pm), &pPerm));
2883 *pdwAction = m_LiteWeightStgdb.m_MiniMd.getActionOfDeclSecurity(pPerm);
2884 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPermissionSetOfDeclSecurity(pPerm, (const BYTE **)ppvPermission, pcbPermission));
2885
2886 return S_OK;
2887} // MDInternalRO::GetPermissionSetProps
2888
2889//*****************************************************************************
2890// Get the String given the String token.
2891// Return a pointer to the string, or NULL in case of error.
2892//*****************************************************************************
2893__checkReturn
2894HRESULT
2895MDInternalRO::GetUserString( // Offset into the string blob heap.
2896 mdString stk, // [IN] the string token.
2897 ULONG *pcchStringSize, // [OUT] count of characters in the string.
2898 BOOL *pfIs80Plus, // [OUT] specifies where there are extended characters >= 0x80.
2899 LPCWSTR *pwszUserString)
2900{
2901 HRESULT hr;
2902 LPWSTR wszTmp;
2903
2904 if (pfIs80Plus != NULL)
2905 {
2906 *pfIs80Plus = FALSE;
2907 }
2908 *pwszUserString = NULL;
2909 *pcchStringSize = 0;
2910
2911 _ASSERTE(pcchStringSize != NULL);
2912 MetaData::DataBlob userString;
2913 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetUserString(RidFromToken(stk), &userString));
2914
2915 wszTmp = reinterpret_cast<LPWSTR>(userString.GetDataPointer());
2916
2917 *pcchStringSize = userString.GetSize() / sizeof(WCHAR);
2918
2919 if (userString.IsEmpty())
2920 {
2921 *pwszUserString = NULL;
2922 return S_OK;
2923 }
2924
2925 if (pfIs80Plus != NULL)
2926 {
2927 if (userString.GetSize() % sizeof(WCHAR) == 0)
2928 {
2929 *pfIs80Plus = TRUE; // no indicator, presume the worst
2930 }
2931 // Return the user string terminator (contains value fIs80Plus)
2932 *pfIs80Plus = *(reinterpret_cast<PBYTE>(wszTmp + *pcchStringSize));
2933 }
2934
2935 *pwszUserString = wszTmp;
2936 return S_OK;
2937} // MDInternalRO::GetUserString
2938
2939//*****************************************************************************
2940// Return contents of Pinvoke given the forwarded member token.
2941//*****************************************************************************
2942__checkReturn
2943HRESULT MDInternalRO::GetPinvokeMap(
2944 mdToken tk, // [IN] FieldDef or MethodDef.
2945 DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
2946 LPCSTR *pszImportName, // [OUT] Import name.
2947 mdModuleRef *pmrImportDLL) // [OUT] ModuleRef token for the target DLL.
2948{
2949 HRESULT hr;
2950 ImplMapRec *pRecord;
2951 RID iRecord;
2952
2953 IfFailRet(m_LiteWeightStgdb.m_MiniMd.FindImplMapFor(RidFromToken(tk), TypeFromToken(tk), &iRecord));
2954 if (InvalidRid(iRecord))
2955 {
2956 return CLDB_E_RECORD_NOTFOUND;
2957 }
2958 else
2959 {
2960 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetImplMapRecord(iRecord, &pRecord));
2961 }
2962
2963 if (pdwMappingFlags)
2964 *pdwMappingFlags = m_LiteWeightStgdb.m_MiniMd.getMappingFlagsOfImplMap(pRecord);
2965 if (pszImportName != NULL)
2966 {
2967 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getImportNameOfImplMap(pRecord, pszImportName));
2968 }
2969 if (pmrImportDLL)
2970 *pmrImportDLL = m_LiteWeightStgdb.m_MiniMd.getImportScopeOfImplMap(pRecord);
2971
2972 return S_OK;
2973} // MDInternalRO::GetPinvokeMap
2974
2975//*****************************************************************************
2976// Get the properties for the given Assembly token.
2977//*****************************************************************************
2978__checkReturn
2979HRESULT MDInternalRO::GetAssemblyProps(
2980 mdAssembly mda, // [IN] The Assembly for which to get the properties.
2981 const void **ppbPublicKey, // [OUT] Pointer to the public key.
2982 ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key.
2983 ULONG *pulHashAlgId, // [OUT] Hash Algorithm.
2984 LPCSTR *pszName, // [OUT] Buffer to fill with name.
2985 AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData.
2986 DWORD *pdwAssemblyFlags) // [OUT] Flags.
2987{
2988 HRESULT hr;
2989 AssemblyRec *pRecord;
2990
2991 _ASSERTE(TypeFromToken(mda) == mdtAssembly && RidFromToken(mda));
2992 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetAssemblyRecord(RidFromToken(mda), &pRecord));
2993
2994 if (ppbPublicKey != NULL)
2995 {
2996 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, reinterpret_cast<const BYTE **>(ppbPublicKey), pcbPublicKey));
2997 }
2998 if (pulHashAlgId)
2999 *pulHashAlgId = m_LiteWeightStgdb.m_MiniMd.getHashAlgIdOfAssembly(pRecord);
3000 if (pszName != NULL)
3001 {
3002 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfAssembly(pRecord, pszName));
3003 }
3004 if (pMetaData)
3005 {
3006 pMetaData->usMajorVersion = m_LiteWeightStgdb.m_MiniMd.getMajorVersionOfAssembly(pRecord);
3007 pMetaData->usMinorVersion = m_LiteWeightStgdb.m_MiniMd.getMinorVersionOfAssembly(pRecord);
3008 pMetaData->usBuildNumber = m_LiteWeightStgdb.m_MiniMd.getBuildNumberOfAssembly(pRecord);
3009 pMetaData->usRevisionNumber = m_LiteWeightStgdb.m_MiniMd.getRevisionNumberOfAssembly(pRecord);
3010 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getLocaleOfAssembly(pRecord, &pMetaData->szLocale));
3011 pMetaData->ulProcessor = 0;
3012 pMetaData->ulOS = 0;
3013 }
3014 if (pdwAssemblyFlags)
3015 {
3016 *pdwAssemblyFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfAssembly(pRecord);
3017
3018#ifdef FEATURE_WINDOWSPHONE
3019 // Turn on the afPublicKey if PublicKey blob is not empty
3020 DWORD cbPublicKey;
3021 const BYTE *pbPublicKey;
3022 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, &pbPublicKey, &cbPublicKey));
3023 if (cbPublicKey != 0)
3024 *pdwAssemblyFlags |= afPublicKey;
3025#else
3026 if (ppbPublicKey)
3027 {
3028 if (pcbPublicKey && *pcbPublicKey)
3029 *pdwAssemblyFlags |= afPublicKey;
3030 }
3031 else
3032 {
3033#ifdef _DEBUG
3034 // Assert that afPublicKey is set if PublicKey blob is not empty
3035 DWORD cbPublicKey;
3036 const BYTE *pPublicKey;
3037 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOfAssembly(pRecord, &pPublicKey, &cbPublicKey));
3038 bool hasPublicKey = cbPublicKey != 0;
3039 bool hasPublicKeyFlag = ( *pdwAssemblyFlags & afPublicKey ) != 0;
3040 if(REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AssertOnBadImageFormat, 0))
3041 _ASSERTE( hasPublicKey == hasPublicKeyFlag );
3042#endif
3043 }
3044#endif // FEATURE_WINDOWSPHONE
3045 }
3046
3047 return S_OK;
3048} // MDInternalRO::GetAssemblyProps
3049
3050//*****************************************************************************
3051// Get the properties for the given AssemblyRef token.
3052//*****************************************************************************
3053__checkReturn
3054HRESULT MDInternalRO::GetAssemblyRefProps(
3055 mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties.
3056 const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token.
3057 ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token.
3058 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3059 AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData.
3060 const void **ppbHashValue, // [OUT] Hash blob.
3061 ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob.
3062 DWORD *pdwAssemblyRefFlags) // [OUT] Flags.
3063{
3064 HRESULT hr;
3065 AssemblyRefRec *pRecord;
3066
3067 _ASSERTE(TypeFromToken(mdar) == mdtAssemblyRef && RidFromToken(mdar));
3068 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetAssemblyRefRecord(RidFromToken(mdar), &pRecord));
3069
3070 if (ppbPublicKeyOrToken != NULL)
3071 {
3072 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getPublicKeyOrTokenOfAssemblyRef(pRecord, reinterpret_cast<const BYTE **>(ppbPublicKeyOrToken), pcbPublicKeyOrToken));
3073 }
3074 if (pszName != NULL)
3075 {
3076 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfAssemblyRef(pRecord, pszName));
3077 }
3078 if (pMetaData)
3079 {
3080 pMetaData->usMajorVersion = m_LiteWeightStgdb.m_MiniMd.getMajorVersionOfAssemblyRef(pRecord);
3081 pMetaData->usMinorVersion = m_LiteWeightStgdb.m_MiniMd.getMinorVersionOfAssemblyRef(pRecord);
3082 pMetaData->usBuildNumber = m_LiteWeightStgdb.m_MiniMd.getBuildNumberOfAssemblyRef(pRecord);
3083 pMetaData->usRevisionNumber = m_LiteWeightStgdb.m_MiniMd.getRevisionNumberOfAssemblyRef(pRecord);
3084 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getLocaleOfAssemblyRef(pRecord, &pMetaData->szLocale));
3085 pMetaData->ulProcessor = 0;
3086 pMetaData->ulOS = 0;
3087 }
3088 if (ppbHashValue != NULL)
3089 {
3090 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getHashValueOfAssemblyRef(pRecord, reinterpret_cast<const BYTE **>(ppbHashValue), pcbHashValue));
3091 }
3092 if (pdwAssemblyRefFlags != NULL)
3093 {
3094 *pdwAssemblyRefFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfAssemblyRef(pRecord);
3095 }
3096
3097 return S_OK;
3098} // MDInternalRO::GetAssemblyRefProps
3099
3100//*****************************************************************************
3101// Get the properties for the given File token.
3102//*****************************************************************************
3103__checkReturn
3104HRESULT MDInternalRO::GetFileProps(
3105 mdFile mdf, // [IN] The File for which to get the properties.
3106 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3107 const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob.
3108 ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob.
3109 DWORD *pdwFileFlags) // [OUT] Flags.
3110{
3111 HRESULT hr;
3112 FileRec *pRecord;
3113
3114 _ASSERTE(TypeFromToken(mdf) == mdtFile && RidFromToken(mdf));
3115 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetFileRecord(RidFromToken(mdf), &pRecord));
3116
3117 if (pszName != NULL)
3118 {
3119 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfFile(pRecord, pszName));
3120 }
3121 if (ppbHashValue != NULL)
3122 {
3123 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getHashValueOfFile(pRecord, reinterpret_cast<const BYTE **>(ppbHashValue), pcbHashValue));
3124 }
3125 if (pdwFileFlags != NULL)
3126 {
3127 *pdwFileFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfFile(pRecord);
3128 }
3129
3130 return S_OK;
3131} // MDInternalRO::GetFileProps
3132
3133//*****************************************************************************
3134// Get the properties for the given ExportedType token.
3135//*****************************************************************************
3136__checkReturn
3137HRESULT MDInternalRO::GetExportedTypeProps(
3138 mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
3139 LPCSTR *pszNamespace, // [OUT] Buffer to fill with namespace.
3140 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3141 mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
3142 mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file.
3143 DWORD *pdwExportedTypeFlags) // [OUT] Flags.
3144{
3145 HRESULT hr;
3146 ExportedTypeRec *pRecord;
3147
3148 _ASSERTE(TypeFromToken(mdct) == mdtExportedType && RidFromToken(mdct));
3149 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetExportedTypeRecord(RidFromToken(mdct), &pRecord));
3150
3151 if (pszNamespace != NULL)
3152 {
3153 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeNamespaceOfExportedType(pRecord, pszNamespace));
3154 }
3155 if (pszName != NULL)
3156 {
3157 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getTypeNameOfExportedType(pRecord, pszName));
3158 }
3159 if (ptkImplementation)
3160 *ptkImplementation = m_LiteWeightStgdb.m_MiniMd.getImplementationOfExportedType(pRecord);
3161 if (ptkTypeDef)
3162 *ptkTypeDef = m_LiteWeightStgdb.m_MiniMd.getTypeDefIdOfExportedType(pRecord);
3163 if (pdwExportedTypeFlags)
3164 *pdwExportedTypeFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfExportedType(pRecord);
3165
3166 return S_OK;
3167} // MDInternalRO::GetExportedTypeProps
3168
3169//*****************************************************************************
3170// Get the properties for the given Resource token.
3171//*****************************************************************************
3172__checkReturn
3173HRESULT MDInternalRO::GetManifestResourceProps(
3174 mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties.
3175 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3176 mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
3177 DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file.
3178 DWORD *pdwResourceFlags) // [OUT] Flags.
3179{
3180 HRESULT hr;
3181 ManifestResourceRec *pRecord;
3182
3183 _ASSERTE(TypeFromToken(mdmr) == mdtManifestResource && RidFromToken(mdmr));
3184 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetManifestResourceRecord(RidFromToken(mdmr), &pRecord));
3185
3186 if (pszName != NULL)
3187 {
3188 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfManifestResource(pRecord, pszName));
3189 }
3190 if (ptkImplementation)
3191 *ptkImplementation = m_LiteWeightStgdb.m_MiniMd.getImplementationOfManifestResource(pRecord);
3192 if (pdwOffset)
3193 *pdwOffset = m_LiteWeightStgdb.m_MiniMd.getOffsetOfManifestResource(pRecord);
3194 if (pdwResourceFlags)
3195 *pdwResourceFlags = m_LiteWeightStgdb.m_MiniMd.getFlagsOfManifestResource(pRecord);
3196
3197 return S_OK;
3198} // MDInternalRO::GetManifestResourceProps
3199
3200//*****************************************************************************
3201// Find the ExportedType given the name.
3202//*****************************************************************************
3203__checkReturn
3204STDMETHODIMP MDInternalRO::FindExportedTypeByName( // S_OK or error
3205 LPCSTR szNamespace, // [IN] Namespace of the ExportedType.
3206 LPCSTR szName, // [IN] Name of the ExportedType.
3207 mdExportedType tkEnclosingType, // [IN] Token for the Enclosing Type.
3208 mdExportedType *pmct) // [OUT] Put ExportedType token here.
3209{
3210 IMetaModelCommon *pCommon = static_cast<IMetaModelCommon*>(&m_LiteWeightStgdb.m_MiniMd);
3211 return pCommon->CommonFindExportedType(szNamespace, szName, tkEnclosingType, pmct);
3212} // MDInternalRO::FindExportedTypeByName
3213
3214//*****************************************************************************
3215// Find the ManifestResource given the name.
3216//*****************************************************************************
3217__checkReturn
3218STDMETHODIMP MDInternalRO::FindManifestResourceByName( // S_OK or error
3219 LPCSTR szName, // [IN] Name of the resource.
3220 mdManifestResource *pmmr) // [OUT] Put ManifestResource token here.
3221{
3222 _ASSERTE(szName && pmmr);
3223
3224 HRESULT hr;
3225 ManifestResourceRec *pRecord;
3226 ULONG cRecords; // Count of records.
3227 LPCUTF8 szNameTmp = 0; // Name obtained from the database.
3228 ULONG i;
3229
3230 cRecords = m_LiteWeightStgdb.m_MiniMd.getCountManifestResources();
3231
3232 // Search for the ExportedType.
3233 for (i = 1; i <= cRecords; i++)
3234 {
3235 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetManifestResourceRecord(i, &pRecord));
3236 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getNameOfManifestResource(pRecord, &szNameTmp));
3237 if (! strcmp(szName, szNameTmp))
3238 {
3239 *pmmr = TokenFromRid(i, mdtManifestResource);
3240 return S_OK;
3241 }
3242 }
3243 return CLDB_E_RECORD_NOTFOUND;
3244} // MDInternalRO::FindManifestResourceByName
3245
3246//*****************************************************************************
3247// Get the Assembly token from the given scope.
3248//*****************************************************************************
3249__checkReturn
3250HRESULT MDInternalRO::GetAssemblyFromScope( // S_OK or error
3251 mdAssembly *ptkAssembly) // [OUT] Put token here.
3252{
3253 _ASSERTE(ptkAssembly);
3254
3255 if (m_LiteWeightStgdb.m_MiniMd.getCountAssemblys())
3256 {
3257 *ptkAssembly = TokenFromRid(1, mdtAssembly);
3258 return S_OK;
3259 }
3260 else
3261 return CLDB_E_RECORD_NOTFOUND;
3262} // MDInternalRO::GetAssemblyFromScope
3263
3264//*******************************************************************************
3265// return properties regarding a TypeSpec
3266//*******************************************************************************
3267__checkReturn
3268HRESULT MDInternalRO::GetTypeSpecFromToken( // S_OK or error.
3269 mdTypeSpec typespec, // [IN] Signature token.
3270 PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token.
3271 ULONG *pcbSig) // [OUT] return size of signature.
3272{
3273 HRESULT hr = NOERROR;
3274
3275 _ASSERTE(TypeFromToken(typespec) == mdtTypeSpec);
3276 _ASSERTE(ppvSig && pcbSig);
3277
3278 if (!IsValidToken(typespec))
3279 {
3280 *ppvSig = NULL;
3281 *pcbSig = 0;
3282 return E_INVALIDARG;
3283 }
3284
3285 TypeSpecRec *pRec;
3286 IfFailRet(m_LiteWeightStgdb.m_MiniMd.GetTypeSpecRecord(RidFromToken(typespec), &pRec));
3287
3288 if (pRec == NULL)
3289 {
3290 *ppvSig = NULL;
3291 *pcbSig = 0;
3292 return CLDB_E_FILE_CORRUPT;
3293 }
3294
3295 IfFailRet(m_LiteWeightStgdb.m_MiniMd.getSignatureOfTypeSpec(pRec, ppvSig, pcbSig));
3296
3297 return hr;
3298} // MDInternalRO::GetTypeSpecFromToken
3299
3300//*****************************************************************************
3301// This function gets the "built for" version of a metadata scope.
3302// NOTE: if the scope has never been saved, it will not have a built-for
3303// version, and an empty string will be returned.
3304//*****************************************************************************
3305__checkReturn
3306HRESULT MDInternalRO::GetVersionString(
3307 LPCSTR * pVer) // [OUT] Put version string here.
3308{
3309 HRESULT hr = NOERROR;
3310
3311 if (m_LiteWeightStgdb.m_pvMd != NULL)
3312 {
3313 // For convenience, get a pointer to the version string.
3314 // @todo: get from alternate locations when there is no STOREAGESIGNATURE.
3315 *pVer = reinterpret_cast<const char*>(reinterpret_cast<const STORAGESIGNATURE*>(m_LiteWeightStgdb.m_pvMd)->pVersion);
3316 }
3317 else
3318 { // No string.
3319 *pVer = NULL;
3320 }
3321
3322 return hr;
3323} // MDInternalRO::GetVersionString
3324
3325//*****************************************************************************
3326// convert a text signature to com format
3327//*****************************************************************************
3328__checkReturn
3329HRESULT MDInternalRO::ConvertTextSigToComSig(// Return hresult.
3330 BOOL fCreateTrIfNotFound, // create typeref if not found or not
3331 LPCSTR pSignature, // class file format signature
3332 CQuickBytes *pqbNewSig, // [OUT] place holder for COM+ signature
3333 ULONG *pcbCount) // [OUT] the result size of signature
3334{
3335 return E_NOTIMPL;
3336} // MDInternalRO::ConvertTextSigToComSig
3337
3338
3339//*****************************************************************************
3340// determine if a token is valid or not
3341//*****************************************************************************
3342BOOL MDInternalRO::IsValidToken( // True or False.
3343 mdToken tk) // [IN] Given token.
3344{
3345 RID rid = RidFromToken(tk);
3346 if (rid == 0)
3347 {
3348 return FALSE;
3349 }
3350 switch (TypeFromToken(tk))
3351 {
3352 case mdtModule:
3353 // can have only one module record
3354 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountModules());
3355 case mdtTypeRef:
3356 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeRefs());
3357 case mdtTypeDef:
3358 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeDefs());
3359 case mdtFieldDef:
3360 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountFields());
3361 case mdtMethodDef:
3362 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMethods());
3363 case mdtParamDef:
3364 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountParams());
3365 case mdtInterfaceImpl:
3366 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountInterfaceImpls());
3367 case mdtMemberRef:
3368 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMemberRefs());
3369 case mdtCustomAttribute:
3370 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountCustomAttributes());
3371 case mdtPermission:
3372 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountDeclSecuritys());
3373 case mdtSignature:
3374 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountStandAloneSigs());
3375 case mdtEvent:
3376 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountEvents());
3377 case mdtProperty:
3378 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountPropertys());
3379 case mdtModuleRef:
3380 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountModuleRefs());
3381 case mdtTypeSpec:
3382 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountTypeSpecs());
3383 case mdtAssembly:
3384 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountAssemblys());
3385 case mdtAssemblyRef:
3386 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountAssemblyRefs());
3387 case mdtFile:
3388 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountFiles());
3389 case mdtExportedType:
3390 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountExportedTypes());
3391 case mdtManifestResource:
3392 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountManifestResources());
3393 case mdtMethodSpec:
3394 return (rid <= m_LiteWeightStgdb.m_MiniMd.getCountMethodSpecs());
3395 case mdtString:
3396 // need to check the user string heap
3397 return m_LiteWeightStgdb.m_MiniMd.m_UserStringHeap.IsValidIndex(rid);
3398 default:
3399/* Don't Assert here, this will break verifier tests.
3400 _ASSERTE(!"Unknown token kind!");
3401*/
3402 return FALSE;
3403 }
3404} // MDInternalRO::IsValidToken
3405
3406mdModule MDInternalRO::GetModuleFromScope(void)
3407{
3408 return TokenFromRid(1, mdtModule);
3409} // MDInternalRO::GetModuleFromScope
3410
3411//*****************************************************************************
3412// Fill a variant given a MDDefaultValue
3413// This routine will create a bstr if the ELEMENT_TYPE of default value is STRING
3414//*****************************************************************************
3415__checkReturn
3416HRESULT _FillVariant(
3417 MDDefaultValue *pMDDefaultValue,
3418 VARIANT *pvar)
3419{
3420 HRESULT hr = NOERROR;
3421
3422 _ASSERTE(pMDDefaultValue);
3423
3424 switch (pMDDefaultValue->m_bType)
3425 {
3426 case ELEMENT_TYPE_BOOLEAN:
3427 V_VT(pvar) = VT_BOOL;
3428 V_BOOL(pvar) = pMDDefaultValue->m_bValue;
3429 break;
3430 case ELEMENT_TYPE_I1:
3431 V_VT(pvar) = VT_I1;
3432 V_I1(pvar) = pMDDefaultValue->m_cValue;
3433 break;
3434 case ELEMENT_TYPE_U1:
3435 V_VT(pvar) = VT_UI1;
3436 V_UI1(pvar) = pMDDefaultValue->m_byteValue;
3437 break;
3438 case ELEMENT_TYPE_I2:
3439 V_VT(pvar) = VT_I2;
3440 V_I2(pvar) = pMDDefaultValue->m_sValue;
3441 break;
3442 case ELEMENT_TYPE_U2:
3443 case ELEMENT_TYPE_CHAR: // char is stored as UI2 internally
3444 V_VT(pvar) = VT_UI2;
3445 V_UI2(pvar) = pMDDefaultValue->m_usValue;
3446 break;
3447 case ELEMENT_TYPE_I4:
3448 V_VT(pvar) = VT_I4;
3449 V_I4(pvar) = pMDDefaultValue->m_lValue;
3450 break;
3451 case ELEMENT_TYPE_U4:
3452 V_VT(pvar) = VT_UI4;
3453 V_UI4(pvar) = pMDDefaultValue->m_ulValue;
3454 break;
3455 case ELEMENT_TYPE_R4:
3456 V_VT(pvar) = VT_R4;
3457 V_R4(pvar) = pMDDefaultValue->m_fltValue;
3458 break;
3459 case ELEMENT_TYPE_R8:
3460 V_VT(pvar) = VT_R8;
3461 V_R8(pvar) = pMDDefaultValue->m_dblValue;
3462 break;
3463 case ELEMENT_TYPE_STRING:
3464 // allocated bstr here
3465 V_BSTR(pvar) = ::SysAllocStringLen(pMDDefaultValue->m_wzValue, pMDDefaultValue->m_cbSize / sizeof(WCHAR));
3466 if (V_BSTR(pvar) == NULL)
3467 hr = E_OUTOFMEMORY;
3468 V_VT(pvar) = VT_BSTR;
3469 break;
3470 case ELEMENT_TYPE_CLASS:
3471 V_VT(pvar) = VT_UNKNOWN;
3472 V_UNKNOWN(pvar) = pMDDefaultValue->m_unkValue;
3473 break;
3474 case ELEMENT_TYPE_I8:
3475 V_VT(pvar) = VT_I8;
3476 V_CY(pvar).int64 = pMDDefaultValue->m_llValue;
3477 break;
3478 case ELEMENT_TYPE_U8:
3479 V_VT(pvar) = VT_UI8;
3480 V_CY(pvar).int64 = pMDDefaultValue->m_ullValue;
3481 break;
3482 case ELEMENT_TYPE_VOID:
3483 V_VT(pvar) = VT_EMPTY;
3484 break;
3485 default:
3486 _ASSERTE(!"bad constant value type!");
3487 }
3488
3489 return hr;
3490} // _FillVariant
3491
3492
3493//*****************************************************************************
3494// Fill a variant given a MDDefaultValue
3495// This routine will create a bstr if the ELEMENT_TYPE of default value is STRING
3496//*****************************************************************************
3497__checkReturn
3498HRESULT _FillMDDefaultValue(
3499 BYTE bType,
3500 void const *pValue,
3501 ULONG cbValue,
3502 MDDefaultValue *pMDDefaultValue)
3503{
3504 HRESULT hr = NOERROR;
3505
3506 pMDDefaultValue->m_bType = bType;
3507 pMDDefaultValue->m_cbSize = cbValue;
3508 switch (bType)
3509 {
3510 case ELEMENT_TYPE_BOOLEAN:
3511 if (cbValue < 1)
3512 {
3513 IfFailGo(CLDB_E_FILE_CORRUPT);
3514 }
3515 pMDDefaultValue->m_bValue = *((BYTE *) pValue);
3516 break;
3517 case ELEMENT_TYPE_I1:
3518 if (cbValue < 1)
3519 {
3520 IfFailGo(CLDB_E_FILE_CORRUPT);
3521 }
3522 pMDDefaultValue->m_cValue = *((CHAR *) pValue);
3523 break;
3524 case ELEMENT_TYPE_U1:
3525 if (cbValue < 1)
3526 {
3527 IfFailGo(CLDB_E_FILE_CORRUPT);
3528 }
3529 pMDDefaultValue->m_byteValue = *((BYTE *) pValue);
3530 break;
3531 case ELEMENT_TYPE_I2:
3532 if (cbValue < 2)
3533 {
3534 IfFailGo(CLDB_E_FILE_CORRUPT);
3535 }
3536 pMDDefaultValue->m_sValue = GET_UNALIGNED_VAL16(pValue);
3537 break;
3538 case ELEMENT_TYPE_U2:
3539 case ELEMENT_TYPE_CHAR:
3540 if (cbValue < 2)
3541 {
3542 IfFailGo(CLDB_E_FILE_CORRUPT);
3543 }
3544 pMDDefaultValue->m_usValue = GET_UNALIGNED_VAL16(pValue);
3545 break;
3546 case ELEMENT_TYPE_I4:
3547 if (cbValue < 4)
3548 {
3549 IfFailGo(CLDB_E_FILE_CORRUPT);
3550 }
3551 pMDDefaultValue->m_lValue = GET_UNALIGNED_VAL32(pValue);
3552 break;
3553 case ELEMENT_TYPE_U4:
3554 if (cbValue < 4)
3555 {
3556 IfFailGo(CLDB_E_FILE_CORRUPT);
3557 }
3558 pMDDefaultValue->m_ulValue = GET_UNALIGNED_VAL32(pValue);
3559 break;
3560 case ELEMENT_TYPE_R4:
3561 {
3562 if (cbValue < 4)
3563 {
3564 IfFailGo(CLDB_E_FILE_CORRUPT);
3565 }
3566 __int32 Value = GET_UNALIGNED_VAL32(pValue);
3567 pMDDefaultValue->m_fltValue = (float &)Value;
3568 }
3569 break;
3570 case ELEMENT_TYPE_R8:
3571 {
3572 if (cbValue < 8)
3573 {
3574 IfFailGo(CLDB_E_FILE_CORRUPT);
3575 }
3576 __int64 Value = GET_UNALIGNED_VAL64(pValue);
3577 pMDDefaultValue->m_dblValue = (double &) Value;
3578 }
3579 break;
3580 case ELEMENT_TYPE_STRING:
3581 if (cbValue == 0)
3582 pValue = NULL;
3583
3584#if BIGENDIAN
3585 {
3586 // We need to allocate and swap the string if we're on a big endian
3587 pMDDefaultValue->m_wzValue = new WCHAR[(cbValue + 1) / sizeof (WCHAR)];
3588 _ASSERTE(FALSE); // Nothing ever free's this newly allocated array. Inserting assert so that if we ever actually
3589 // use this code path, we'll fix it then. (Don't want to fix something I can't test.)
3590 IfNullGo(pMDDefaultValue->m_wzValue);
3591 memcpy(const_cast<WCHAR *>(pMDDefaultValue->m_wzValue), pValue, cbValue);
3592 _ASSERTE(cbValue % sizeof(WCHAR) == 0);
3593 SwapStringLength(const_cast<WCHAR *>(pMDDefaultValue->m_wzValue), cbValue / sizeof(WCHAR));
3594 }
3595#else
3596 pMDDefaultValue->m_wzValue = (LPWSTR) pValue;
3597#endif
3598 break;
3599 case ELEMENT_TYPE_CLASS:
3600 //
3601 // There is only a 4-byte quantity in the MetaData, and it must always
3602 // be zero. So, we load an INT32 and zero-extend it to be pointer-sized.
3603 //
3604 if (cbValue < 4)
3605 {
3606 IfFailGo(CLDB_E_FILE_CORRUPT);
3607 }
3608 pMDDefaultValue->m_unkValue = (IUnknown *)(UINT_PTR)GET_UNALIGNED_VAL32(pValue);
3609 if (pMDDefaultValue->m_unkValue != NULL)
3610 {
3611 _ASSERTE(!"Non-NULL objectref's are not supported as default values!");
3612 IfFailGo(CLDB_E_FILE_CORRUPT);
3613 }
3614 break;
3615 case ELEMENT_TYPE_I8:
3616 if (cbValue < 8)
3617 {
3618 IfFailGo(CLDB_E_FILE_CORRUPT);
3619 }
3620 pMDDefaultValue->m_llValue = GET_UNALIGNED_VAL64(pValue);
3621 break;
3622 case ELEMENT_TYPE_U8:
3623 if (cbValue < 8)
3624 {
3625 IfFailGo(CLDB_E_FILE_CORRUPT);
3626 }
3627 pMDDefaultValue->m_ullValue = GET_UNALIGNED_VAL64(pValue);
3628 break;
3629 case ELEMENT_TYPE_VOID:
3630 break;
3631 default:
3632 _ASSERTE(!"BAD TYPE!");
3633 IfFailGo(CLDB_E_FILE_CORRUPT);
3634 break;
3635 }
3636ErrExit:
3637 return hr;
3638} // _FillMDDefaultValue
3639
3640//*****************************************************************************
3641// Given a scope, return the table size and table ptr for a given index
3642//*****************************************************************************
3643__checkReturn
3644HRESULT MDInternalRO::GetTableInfoWithIndex( // return size
3645 ULONG index, // [IN] pass in the index
3646 void **pTable, // [OUT] pointer to table at index
3647 void **pTableSize) // [OUT] size of table at index
3648{
3649 _ASSERTE(!"NYI");
3650 return E_NOTIMPL;
3651} // MDInternalRO::GetTableInfoWithIndex
3652
3653
3654
3655//*****************************************************************************
3656// Given a delta metadata byte stream, apply the changes to the current metadata
3657// object returning the resulting metadata object in ppv
3658//*****************************************************************************
3659__checkReturn
3660HRESULT MDInternalRO::ApplyEditAndContinue(
3661 void *pDeltaMD, // [IN] the delta metadata
3662 ULONG cbDeltaMD, // [IN] length of pData
3663 IMDInternalImport **ppv) // [OUT] the resulting metadata interface
3664{
3665 _ASSERTE(pDeltaMD);
3666 _ASSERTE(ppv);
3667
3668 HRESULT hr = E_FAIL;
3669
3670 IMDInternalImportENC *pDeltaMDImport = NULL;
3671
3672 IfFailGo(GetInternalWithRWFormat(pDeltaMD, cbDeltaMD, 0, IID_IMDInternalImportENC, (void**)&pDeltaMDImport));
3673
3674 *ppv = this;
3675 IfFailGo(MDApplyEditAndContinue(ppv, pDeltaMDImport));
3676
3677ErrExit:
3678 if (pDeltaMDImport)
3679 pDeltaMDImport->Release();
3680 return hr;
3681}
3682
3683HRESULT MDInternalRO::GetRvaOffsetData(
3684 DWORD *pFirstMethodRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in MethodDef table.
3685 DWORD *pMethodDefRecordSize, // [OUT] Size of each record in MethodDef table.
3686 DWORD *pMethodDefCount, // [OUT] Number of records in MethodDef table.
3687 DWORD *pFirstFieldRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in FieldRVA table.
3688 DWORD *pFieldRvaRecordSize, // [OUT] Size of each record in FieldRVA table.
3689 DWORD *pFieldRvaCount) // [OUT] Number of records in FieldRVA table.
3690{
3691 HRESULT hr = S_OK;
3692 DWORD methodDefCount = *pMethodDefCount = m_LiteWeightStgdb.m_MiniMd.getCountMethods();
3693 if (methodDefCount == 0)
3694 *pFirstMethodRvaOffset = *pMethodDefRecordSize = 0;
3695 else
3696 {
3697 MethodRec *pMethodRec;
3698 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetMethodRecord(1, &pMethodRec));
3699
3700 // RVA is the first column of the MethodDef table, so the address of MethodRec is also address of RVA column.
3701 if ((const BYTE *)m_LiteWeightStgdb.m_pvMd > (const BYTE *)pMethodRec)
3702 {
3703 Debug_ReportError("Stream header is not within MetaData block.");
3704 IfFailGo(CLDB_E_FILE_CORRUPT);
3705 }
3706 *pFirstMethodRvaOffset = (DWORD)((const BYTE *)pMethodRec - (const BYTE *)m_LiteWeightStgdb.m_pvMd);
3707 *pMethodDefRecordSize = m_LiteWeightStgdb.m_MiniMd._CBREC(Method);
3708 }
3709
3710 {
3711 DWORD fieldRvaCount = *pFieldRvaCount = m_LiteWeightStgdb.m_MiniMd.getCountFieldRVAs();
3712 if (fieldRvaCount == 0)
3713 *pFirstFieldRvaOffset = *pFieldRvaRecordSize = 0;
3714 else
3715 {
3716
3717 // orig
3718 // FieldRVARec *pFieldRVARec = m_LiteWeightStgdb.m_MiniMd.getFieldRVA(1);
3719 FieldRVARec *pFieldRVARec;
3720 IfFailGo(m_LiteWeightStgdb.m_MiniMd.GetFieldRVARecord(1, &pFieldRVARec));
3721
3722//FieldRVARec *pFieldRVARec;
3723//mdToken fakeTok = 1;
3724//RidToToken(&fakeTok, mdtFieldDef);
3725//GetFieldRVA(fakeTok, &pFieldRVARec);
3726 // RVA is the first column of the FieldRVA table, so the address of FieldRVARec is also address of RVA column.
3727 if ((const BYTE *)m_LiteWeightStgdb.m_pvMd > (const BYTE *)pFieldRVARec)
3728 {
3729 Debug_ReportError("Stream header is not within MetaData block.");
3730 IfFailGo(CLDB_E_FILE_CORRUPT);
3731 }
3732 *pFirstFieldRvaOffset = (DWORD)((const BYTE *)pFieldRVARec - (const BYTE *)m_LiteWeightStgdb.m_pvMd);
3733 *pFieldRvaRecordSize = m_LiteWeightStgdb.m_MiniMd._CBREC(FieldRVA);
3734 }
3735 }
3736 hr = S_OK;
3737
3738ErrExit:
3739 return hr;
3740}
3741
3742#endif //FEATURE_METADATA_INTERNAL_APIS
3743