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: MDInternalRW.cpp
6//
7
8// Notes:
9//
10//
11// ===========================================================================
12#include "stdafx.h"
13#include "../runtime/mdinternalro.h"
14#include "../compiler/regmeta.h"
15#include "../compiler/importhelper.h"
16#include "mdinternalrw.h"
17#include "metamodelro.h"
18#include "liteweightstgdb.h"
19
20#ifdef FEATURE_METADATA_INTERNAL_APIS
21
22__checkReturn
23HRESULT _GetFixedSigOfVarArg( // S_OK or error.
24 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob of COM+ method signature
25 ULONG cbSigBlob, // [IN] size of signature
26 CQuickBytes *pqbSig, // [OUT] output buffer for fixed part of VarArg Signature
27 ULONG *pcbSigBlob); // [OUT] number of bytes written to the above output buffer
28
29__checkReturn
30HRESULT _FillMDDefaultValue(
31 BYTE bType,
32 void const *pValue,
33 ULONG cbValue,
34 MDDefaultValue *pMDDefaultValue);
35
36
37//*****************************************************************************
38// Serve as a delegator to call ImportHelper::MergeUpdateTokenInSig. Or we will
39// need to include ImportHelper into our md\runtime directory.
40//*****************************************************************************
41__checkReturn
42HRESULT TranslateSigHelper( // S_OK or error.
43 IMDInternalImport* pImport, // [IN] import scope.
44 IMDInternalImport* pAssemImport, // [IN] import assembly scope.
45 const void* pbHashValue, // [IN] hash value for the import assembly.
46 ULONG cbHashValue, // [IN] count of bytes in the hash value.
47 PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope
48 ULONG cbSigBlob, // [IN] count of bytes of signature
49 IMetaDataAssemblyEmit* pAssemEmit, // [IN] assembly emit scope.
50 IMetaDataEmit* emit, // [IN] emit interface
51 CQuickBytes* pqkSigEmit, // [OUT] buffer to hold translated signature
52 ULONG* pcbSig) // [OUT] count of bytes in the translated signature
53{
54#ifdef FEATURE_METADATA_EMIT
55 IMetaModelCommon *pCommon = pImport->GetMetaModelCommon();
56 RegMeta *pAssemEmitRM = static_cast<RegMeta*>(pAssemEmit);
57 RegMeta *pEmitRM = static_cast<RegMeta*>(emit);
58
59 CMiniMdRW *pMiniMdAssemEmit = pAssemEmitRM ? &pAssemEmitRM->m_pStgdb->m_MiniMd : NULL;
60 CMiniMdRW *pMiniMdEmit = &(pEmitRM->m_pStgdb->m_MiniMd);
61 IMetaModelCommon *pCommonAssemImport = pAssemImport ? pAssemImport->GetMetaModelCommon() : NULL;
62
63 return ImportHelper::MergeUpdateTokenInSig(
64 pMiniMdAssemEmit, // The assembly emit scope.
65 pMiniMdEmit, // The emit scope.
66 pCommonAssemImport, // Assembly scope where the signature is from.
67 pbHashValue, // Hash value for the import scope.
68 cbHashValue, // Size in bytes.
69 pCommon, // The scope where signature is from.
70 pbSigBlob, // signature from the imported scope
71 NULL, // Internal OID mapping structure.
72 pqkSigEmit, // [OUT] translated signature
73 NULL, // start from first byte of the signature
74 NULL, // don't care how many bytes consumed
75 pcbSig); // [OUT] total number of bytes write to pqkSigEmit
76
77#else //!FEATURE_METADATA_EMIT
78 // This API doesn't make sense without supporting public Emit APIs
79 return E_NOTIMPL;
80#endif //!FEATURE_METADATA_EMIT
81} // TranslateSigHelper
82
83
84//*****************************************************************************
85// Given an IMDInternalImport on a CMiniMd[RO], convert to CMiniMdRW.
86//*****************************************************************************
87__checkReturn
88STDAPI ConvertRO2RW(
89 IUnknown *pRO, // [IN] The RO interface to convert.
90 REFIID riid, // [IN] The interface desired.
91 void **ppIUnk) // [OUT] Return interface on success.
92{
93 HRESULT hr = S_OK; // A result.
94 IMDInternalImportENC *pRW = 0; // To test the RW-ness of the input iface.
95 MDInternalRW *pInternalRW = 0; // Gets the new RW object.
96 MDInternalRO *pTrustedRO = 0;
97
98 // Avoid confusion.
99 *ppIUnk = 0;
100
101 IfFailGo(VerifyNotWinMD(pRO, "ConvertRO2RW() not supported on .winmd files."));
102
103 // If the interface is already RW, done, just return.
104 if (pRO->QueryInterface(IID_IMDInternalImportENC, (void**)&pRW) == S_OK)
105 {
106 hr = pRO->QueryInterface(riid, ppIUnk);
107 goto ErrExit;
108 }
109
110 // Create the new RW object.
111 pInternalRW = new (nothrow) MDInternalRW;
112 IfNullGo( pInternalRW );
113
114 // Init from the RO object. Convert as read-only; QI will make writable if
115 // so needed.
116
117 // ! QI for IID_IUnknown will return MDInternalRO*. Not that COM guarantees such a thing but MDInternalRO knows about
118 IfFailGo( pRO->QueryInterface(IID_IUnknown, (void**)&pTrustedRO) );
119 IfFailGo( pInternalRW->InitWithRO(pTrustedRO, true));
120 IfFailGo( pInternalRW->QueryInterface(riid, ppIUnk) );
121
122ErrExit:
123 if (pRW)
124 pRW->Release();
125 if (pTrustedRO)
126 pTrustedRO->Release();
127 // Clean up the object and [OUT] interface on error.
128 if (FAILED(hr))
129 {
130 if (pInternalRW)
131 delete pInternalRW;
132 *ppIUnk = 0;
133 }
134 else if (pInternalRW)
135 pInternalRW->Release();
136
137 return hr;
138} // ConvertRO2RW
139
140
141//*****************************************************************************
142// Helper to get the internal interface with RW format
143//*****************************************************************************
144__checkReturn
145HRESULT GetInternalWithRWFormat(
146 LPVOID pData,
147 ULONG cbData,
148 DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC
149 REFIID riid, // [in] The interface desired.
150 void **ppIUnk) // [out] Return interface on success.
151{
152 MDInternalRW *pInternalRW = NULL;
153 HRESULT hr;
154
155 *ppIUnk = 0;
156 pInternalRW = new (nothrow) MDInternalRW;
157 IfNullGo( pInternalRW );
158 IfFailGo( pInternalRW->Init(
159 const_cast<void*>(pData),
160 cbData,
161 (flags == ofRead) ? true : false) );
162 IfFailGo( pInternalRW->QueryInterface(riid, ppIUnk) );
163ErrExit:
164 if (FAILED(hr))
165 {
166 if (pInternalRW)
167 delete pInternalRW;
168 *ppIUnk = 0;
169 }
170 else if ( pInternalRW )
171 pInternalRW->Release();
172 return hr;
173} // GetInternalWithRWFormat
174
175
176//*****************************************************************************
177// This function returns a IMDInternalImport interface based on the given
178// public import interface i.e IMetaDataEmit or IMetaDataImport.
179//*****************************************************************************
180__checkReturn
181STDAPI GetMDInternalInterfaceFromPublic(
182 IUnknown *pIUnkPublic, // [IN] Given public interface. Must be QI of IUnknown
183 REFIID riid, // [in] The interface desired.
184 void **ppIUnkInternal) // [out] Return interface on success.
185{
186 HRESULT hr = S_OK;
187 ReleaseHolder<IGetIMDInternalImport> pGetIMDInternalImport;
188
189 // IMDInternalImport is the only internal import interface currently supported by
190 // this function.
191 _ASSERTE(riid == IID_IMDInternalImport && pIUnkPublic && ppIUnkInternal);
192
193 if (riid != IID_IMDInternalImport || pIUnkPublic == NULL || ppIUnkInternal == NULL)
194 IfFailGo(E_INVALIDARG);
195 IfFailGo( pIUnkPublic->QueryInterface(IID_IGetIMDInternalImport, &pGetIMDInternalImport));
196 IfFailGo( pGetIMDInternalImport->GetIMDInternalImport((IMDInternalImport **)ppIUnkInternal));
197
198ErrExit:
199 if (FAILED(hr))
200 {
201 if (ppIUnkInternal)
202 *ppIUnkInternal = 0;
203 }
204 return hr;
205} // GetMDInternalInterfaceFromPublic
206
207
208//*****************************************************************************
209// This function returns the requested public interface based on the given
210// internal import interface. It is caller's responsibility to Release ppIUnkPublic
211//*****************************************************************************
212__checkReturn
213STDAPI GetMDPublicInterfaceFromInternal(
214 void *pIUnkInternal, // [IN] Given internal interface.
215 REFIID riid, // [in] The interface desired.
216 void **ppIUnkPublic) // [out] Return interface on success.
217{
218 HRESULT hr = S_OK;
219 IMDInternalImport *pInternalImport = 0;;
220 IUnknown *pIUnkPublic = NULL;
221 OptionValue optVal = { MDDupAll, MDRefToDefDefault, MDNotifyDefault, MDUpdateFull, MDErrorOutOfOrderDefault , MDThreadSafetyOn};
222 RegMeta *pMeta = 0;
223 bool isLockedForWrite = false;
224
225
226 _ASSERTE(pIUnkInternal && ppIUnkPublic);
227 *ppIUnkPublic = 0;
228
229 IfFailGo(VerifyNotWinMD((IUnknown*)pIUnkInternal, "GetMDPublicInterfaceFromInternal() not supported on .winmd files."));
230
231 IfFailGo(ConvertRO2RW((IUnknown*)pIUnkInternal, IID_IMDInternalImport, (void **)&pInternalImport));
232
233 pIUnkPublic = pInternalImport->GetCachedPublicInterface(TRUE);
234 if ( pIUnkPublic )
235 {
236 // There is already a cached public interface. GetCachedPublicInterface already AddRef the returned
237 // public interface. We want to QueryInterface the riid...
238 // We are done!
239 hr = pIUnkPublic->QueryInterface(riid, ppIUnkPublic);
240 pIUnkPublic->Release();
241 goto ErrExit;
242 }
243
244 // grab the write lock when we are creating the corresponding regmeta for the public interface
245 _ASSERTE( pInternalImport->GetReaderWriterLock() != NULL );
246 isLockedForWrite = true;
247 IfFailGo(pInternalImport->GetReaderWriterLock()->LockWrite());
248
249 // check again. Maybe someone else beat us to setting the public interface while we are waiting
250 // for the write lock. Don't need to grab the read lock since we already have the write lock.
251 *ppIUnkPublic = pInternalImport->GetCachedPublicInterface(FALSE);
252 if ( *ppIUnkPublic )
253 {
254 // there is already a cached public interface. GetCachedPublicInterface already AddRef the returned
255 // public interface.
256 // We are done!
257 goto ErrExit;
258 }
259
260 pMeta = new (nothrow) RegMeta();
261 IfNullGo(pMeta);
262 IfFailGo(pMeta->SetOption(&optVal));
263 IfFailGo( pMeta->InitWithStgdb((IUnknown*)pInternalImport, ((MDInternalRW*)pInternalImport)->GetMiniStgdb()) );
264 IfFailGo( pMeta->QueryInterface(riid, ppIUnkPublic) );
265
266 // The following makes the public object and the internal object point to each other.
267 _ASSERTE( pMeta->GetReaderWriterLock() == NULL );
268 IfFailGo( pMeta->SetCachedInternalInterface(pInternalImport) );
269 IfFailGo( pInternalImport->SetCachedPublicInterface((IUnknown *) *ppIUnkPublic) );
270 IfFailGo( pMeta->SetReaderWriterLock(pInternalImport->GetReaderWriterLock() ));
271
272 // Add the new RegMeta to the cache.
273 IfFailGo( pMeta->AddToCache() );
274
275ErrExit:
276 if (isLockedForWrite)
277 pInternalImport->GetReaderWriterLock()->UnlockWrite();
278
279 if (pInternalImport)
280 pInternalImport->Release();
281
282 if (FAILED(hr))
283 {
284 if (pMeta)
285 delete pMeta;
286 *ppIUnkPublic = 0;
287 }
288 return hr;
289} // GetMDPublicInterfaceFromInternal
290
291//*****************************************************************************
292// Converts an internal MD import API into the read/write version of this API.
293// This could support edit and continue, or modification of the metadata at
294// runtime (say for profiling).
295//*****************************************************************************
296__checkReturn
297STDAPI ConvertMDInternalImport( // S_OK, S_FALSE (no conversion), or error.
298 IMDInternalImport *pIMD, // [in] The metadata to be updated.
299 IMDInternalImport **ppIMD) // [out] Put the RW here.
300{
301 HRESULT hr; // A result.
302 IMDInternalImportENC *pENC = NULL; // ENC interface on the metadata.
303
304 _ASSERTE(pIMD != NULL);
305 _ASSERTE(ppIMD != NULL);
306
307 // Test whether the MD is already RW.
308 hr = pIMD->QueryInterface(IID_IMDInternalImportENC, (void**)&pENC);
309 if (FAILED(hr))
310 { // Not yet RW, so do the conversion.
311 IfFailGo(ConvertRO2RW(pIMD, IID_IMDInternalImport, (void**)ppIMD));
312 }
313 else
314 { // Already converted; give back same pointer.
315 *ppIMD = pIMD;
316 hr = S_FALSE;
317 }
318
319ErrExit:
320 if (pENC)
321 pENC->Release();
322 return hr;
323} // ConvertMDInternalImport
324
325
326
327
328
329//*****************************************************************************
330// Constructor
331//*****************************************************************************
332MDInternalRW::MDInternalRW()
333 : m_pStgdb(NULL),
334 m_cRefs(1),
335 m_fOwnStgdb(false),
336 m_pUnk(NULL),
337 m_pUserUnk(NULL),
338 m_pIMetaDataHelper(NULL),
339 m_pSemReadWrite(NULL),
340 m_fOwnSem(false)
341{
342} // MDInternalRW::MDInternalRW
343
344
345
346//*****************************************************************************
347// Destructor
348//*****************************************************************************
349MDInternalRW::~MDInternalRW()
350{
351 HRESULT hr = S_OK;
352
353 LOCKWRITENORET();
354
355 // This should have worked if we've cached the internal interface in the past
356 _ASSERTE(SUCCEEDED(hr) || m_pIMetaDataHelper == NULL || m_pIMetaDataHelper->GetCachedInternalInterface(false) == NULL);
357
358
359 if (SUCCEEDED(hr))
360 {
361
362 if (m_pIMetaDataHelper)
363 {
364 // The internal object is going away before the public object.
365 // If the internal object owns the reader writer lock, transfer the ownership
366 // to the public object and clear the cached internal interface from the public interface.
367
368 m_pIMetaDataHelper->SetCachedInternalInterface(NULL);
369 m_pIMetaDataHelper = NULL;
370 m_fOwnSem = false;
371
372 }
373
374 UNLOCKWRITE();
375 }
376 if (m_pSemReadWrite && m_fOwnSem)
377 delete m_pSemReadWrite;
378
379 if ( m_pStgdb && m_fOwnStgdb )
380 {
381 // we own the stgdb so we need to uninit and delete it.
382 m_pStgdb->Uninit();
383 delete m_pStgdb;
384 }
385 if ( m_pUserUnk )
386 m_pUserUnk->Release();
387 if ( m_pUnk )
388 m_pUnk->Release();
389} // MDInternalRW::~MDInternalRW
390
391
392//*****************************************************************************
393// Set or clear the cached public interfaces.
394// NOTE:: Caller should take a Write lock on the reader writer lock.
395//*****************************************************************************
396__checkReturn
397HRESULT MDInternalRW::SetCachedPublicInterface(IUnknown * pUnk)
398{
399 IMetaDataHelper * pHelper = NULL;
400 HRESULT hr = S_OK;
401
402 if (pUnk != NULL)
403 {
404 // Internal object and public regmeta should be one to one mapping!!
405 _ASSERTE(m_pIMetaDataHelper == NULL);
406
407 IfFailRet(pUnk->QueryInterface(IID_IMetaDataHelper, (void **) &pHelper));
408 _ASSERTE(pHelper != NULL);
409
410 m_pIMetaDataHelper = pHelper;
411 pHelper->Release();
412 }
413 else
414 {
415 // public object is going away before the internal object. If we don't own the
416 // reader writer lock, just take over the ownership.
417 m_fOwnSem = true;
418 m_pIMetaDataHelper = NULL;
419 }
420 return hr;
421} // MDInternalRW::SetCachedPublicInterface
422
423
424//*****************************************************************************
425// Clear the cached public interfaces.
426//*****************************************************************************
427IUnknown * MDInternalRW::GetCachedPublicInterface(BOOL fWithLock)
428{
429 HRESULT hr = S_OK;
430 IUnknown * pRet = NULL;
431 if (fWithLock)
432 {
433 LOCKREAD();
434
435 pRet = m_pIMetaDataHelper;
436 if (pRet != NULL)
437 pRet->AddRef();
438 }
439 else
440 {
441 pRet = m_pIMetaDataHelper;
442 if (pRet != NULL)
443 pRet->AddRef();
444 }
445
446ErrExit:
447 return pRet;
448} // MDInternalRW::GetCachedPublicInterface
449
450
451//*****************************************************************************
452// Get the Reader-Writer lock
453//*****************************************************************************
454UTSemReadWrite * MDInternalRW::GetReaderWriterLock()
455{
456 return getReaderWriterLock();
457} // MDInternalRW::GetReaderWriterLock
458
459//*****************************************************************************
460// IUnknown
461//*****************************************************************************
462ULONG MDInternalRW::AddRef()
463{
464 return InterlockedIncrement(&m_cRefs);
465} // MDInternalRW::AddRef
466
467ULONG MDInternalRW::Release()
468{
469 ULONG cRef;
470
471 cRef = InterlockedDecrement(&m_cRefs);
472 if (cRef == 0)
473 {
474 LOG((LOGMD, "MDInternalRW(0x%08x)::destruction\n", this));
475 delete this;
476 }
477 return cRef;
478} // MDInternalRW::Release
479
480__checkReturn
481HRESULT MDInternalRW::QueryInterface(REFIID riid, void **ppUnk)
482{
483 *ppUnk = 0;
484
485 if (riid == IID_IUnknown)
486 *ppUnk = (IUnknown *) (IMDInternalImport *) this;
487
488 else if (riid == IID_IMDInternalImport)
489 *ppUnk = (IMDInternalImport *) this;
490
491 else if (riid == IID_IMDInternalImportENC)
492 *ppUnk = (IMDInternalImportENC *) this;
493
494 else if (riid == IID_IMDCommon)
495 *ppUnk = (IMDCommon*)this;
496
497 else
498 return E_NOINTERFACE;
499 AddRef();
500 return S_OK;
501} // MDInternalRW::QueryInterface
502
503
504//*****************************************************************************
505// Initialize
506//*****************************************************************************
507__checkReturn
508HRESULT MDInternalRW::Init(
509 LPVOID pData, // points to meta data section in memory
510 ULONG cbData, // count of bytes in pData
511 int bReadOnly) // Is it open for read only?
512{
513 CLiteWeightStgdbRW * pStgdb = NULL;
514 HRESULT hr = NOERROR;
515 OptionValue optVal = { MDDupAll, MDRefToDefDefault, MDNotifyDefault, MDUpdateFull, MDErrorOutOfOrderDefault, MDThreadSafetyOn };
516
517 pStgdb = new (nothrow) CLiteWeightStgdbRW;
518 IfNullGo(pStgdb);
519
520 m_pSemReadWrite = new (nothrow) UTSemReadWrite;
521 IfNullGo(m_pSemReadWrite);
522 IfFailGo(m_pSemReadWrite->Init());
523 m_fOwnSem = true;
524 INDEBUG(pStgdb->m_MiniMd.Debug_SetLock(m_pSemReadWrite);)
525
526 IfFailGo(pStgdb->InitOnMem(cbData, (BYTE*)pData, bReadOnly));
527 IfFailGo(pStgdb->m_MiniMd.SetOption(&optVal));
528 m_tdModule = COR_GLOBAL_PARENT_TOKEN;
529 m_fOwnStgdb = true;
530 m_pStgdb = pStgdb;
531
532ErrExit:
533 // clean up upon errors
534 if (FAILED(hr) && (pStgdb != NULL))
535 {
536 delete pStgdb;
537 }
538 return hr;
539} // MDInternalRW::Init
540
541
542//*****************************************************************************
543// Initialize with an existing RegMeta.
544//*****************************************************************************
545__checkReturn
546HRESULT MDInternalRW::InitWithStgdb(
547 IUnknown *pUnk, // The IUnknow that owns the life time for the existing stgdb
548 CLiteWeightStgdbRW *pStgdb) // existing lightweight stgdb
549{
550 // m_fOwnSem should be false because this is the case where we create the internal interface given a public
551 // interface.
552
553 m_tdModule = COR_GLOBAL_PARENT_TOKEN;
554 m_fOwnStgdb = false;
555 m_pStgdb = pStgdb;
556
557 // remember the owner of the light weight stgdb
558 // AddRef it to ensure the lifetime
559 //
560 m_pUnk = pUnk;
561 m_pUnk->AddRef();
562 return NOERROR;
563} // MDInternalRW::InitWithStgdb
564
565
566//*****************************************************************************
567// Initialize with an existing RO format
568//*****************************************************************************
569__checkReturn
570HRESULT MDInternalRW::InitWithRO(
571 MDInternalRO * pRO,
572 int bReadOnly)
573{
574 CLiteWeightStgdbRW * pStgdb = NULL;
575 HRESULT hr = NOERROR;
576 OptionValue optVal = { MDDupAll, MDRefToDefDefault, MDNotifyDefault, MDUpdateFull, MDErrorOutOfOrderDefault, MDThreadSafetyOn };
577
578 pStgdb = new (nothrow) CLiteWeightStgdbRW;
579 IfNullGo(pStgdb);
580
581 m_pSemReadWrite = new (nothrow) UTSemReadWrite;
582 IfNullGo(m_pSemReadWrite);
583 IfFailGo(m_pSemReadWrite->Init());
584 m_fOwnSem = true;
585 INDEBUG(pStgdb->m_MiniMd.Debug_SetLock(m_pSemReadWrite);)
586
587 IfFailGo(pStgdb->m_MiniMd.InitOnRO(&pRO->m_LiteWeightStgdb.m_MiniMd, bReadOnly));
588 IfFailGo(pStgdb->m_MiniMd.SetOption(&optVal));
589 m_tdModule = COR_GLOBAL_PARENT_TOKEN;
590 m_fOwnStgdb = true;
591 pStgdb->m_pvMd=pRO->m_LiteWeightStgdb.m_pvMd;
592 pStgdb->m_cbMd=pRO->m_LiteWeightStgdb.m_cbMd;
593 m_pStgdb = pStgdb;
594
595ErrExit:
596 // clean up upon errors
597 if (FAILED(hr) && (pStgdb != NULL))
598 {
599 delete pStgdb;
600 }
601 return hr;
602} // MDInternalRW::InitWithRO
603
604
605#ifndef DACCESS_COMPILE
606//*****************************************************************************
607// Given a scope, determine whether imported from a typelib.
608//*****************************************************************************
609__checkReturn
610HRESULT MDInternalRW::TranslateSigWithScope(
611 IMDInternalImport* pAssemImport, // [IN] import assembly scope.
612 const void* pbHashValue, // [IN] hash value for the import assembly.
613 ULONG cbHashValue, // [IN] count of bytes in the hash value.
614 PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope
615 ULONG cbSigBlob, // [IN] count of bytes of signature
616 IMetaDataAssemblyEmit* pAssemEmit, // [IN] assembly emit scope.
617 IMetaDataEmit* emit, // [IN] emit interface
618 CQuickBytes* pqkSigEmit, // [OUT] buffer to hold translated signature
619 ULONG* pcbSig) // [OUT] count of bytes in the translated signature
620{
621 return TranslateSigHelper(
622 this,
623 pAssemImport,
624 pbHashValue,
625 cbHashValue,
626 pbSigBlob,
627 cbSigBlob,
628 pAssemEmit,
629 emit,
630 pqkSigEmit,
631 pcbSig);
632} // MDInternalRW::TranslateSigWithScope
633
634__checkReturn
635HRESULT MDInternalRW::GetTypeDefRefTokenInTypeSpec(// return S_FALSE if enclosing type does not have a token
636 mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look at
637 mdToken *tkEnclosedToken) // [OUT] The enclosed type token
638{
639 return m_pStgdb->m_MiniMd.GetTypeDefRefTokenInTypeSpec(tkTypeSpec, tkEnclosedToken);
640}// MDInternalRW::GetTypeDefRefTokenInTypeSpec
641
642//*****************************************************************************
643// Given a scope, return the number of tokens in a given table
644//*****************************************************************************
645ULONG MDInternalRW::GetCountWithTokenKind( // return hresult
646 DWORD tkKind) // [IN] pass in the kind of token.
647{
648 ULONG ulCount = 0;
649 HRESULT hr = S_OK;
650 LOCKREAD();
651
652 switch (tkKind)
653 {
654 case mdtTypeDef:
655 ulCount = m_pStgdb->m_MiniMd.getCountTypeDefs();
656 // Remove global typedef from the count of typedefs (and handle the case where there is no global typedef)
657 if (ulCount > 0)
658 ulCount--;
659 break;
660 case mdtTypeRef:
661 ulCount = m_pStgdb->m_MiniMd.getCountTypeRefs();
662 break;
663 case mdtMethodDef:
664 ulCount = m_pStgdb->m_MiniMd.getCountMethods();
665 break;
666 case mdtFieldDef:
667 ulCount = m_pStgdb->m_MiniMd.getCountFields();
668 break;
669 case mdtMemberRef:
670 ulCount = m_pStgdb->m_MiniMd.getCountMemberRefs();
671 break;
672 case mdtInterfaceImpl:
673 ulCount = m_pStgdb->m_MiniMd.getCountInterfaceImpls();
674 break;
675 case mdtParamDef:
676 ulCount = m_pStgdb->m_MiniMd.getCountParams();
677 break;
678 case mdtFile:
679 ulCount = m_pStgdb->m_MiniMd.getCountFiles();
680 break;
681 case mdtAssemblyRef:
682 ulCount = m_pStgdb->m_MiniMd.getCountAssemblyRefs();
683 break;
684 case mdtAssembly:
685 ulCount = m_pStgdb->m_MiniMd.getCountAssemblys();
686 break;
687 case mdtCustomAttribute:
688 ulCount = m_pStgdb->m_MiniMd.getCountCustomAttributes();
689 break;
690 case mdtModule:
691 ulCount = m_pStgdb->m_MiniMd.getCountModules();
692 break;
693 case mdtPermission:
694 ulCount = m_pStgdb->m_MiniMd.getCountDeclSecuritys();
695 break;
696 case mdtSignature:
697 ulCount = m_pStgdb->m_MiniMd.getCountStandAloneSigs();
698 break;
699 case mdtEvent:
700 ulCount = m_pStgdb->m_MiniMd.getCountEvents();
701 break;
702 case mdtProperty:
703 ulCount = m_pStgdb->m_MiniMd.getCountPropertys();
704 break;
705 case mdtModuleRef:
706 ulCount = m_pStgdb->m_MiniMd.getCountModuleRefs();
707 break;
708 case mdtTypeSpec:
709 ulCount = m_pStgdb->m_MiniMd.getCountTypeSpecs();
710 break;
711 case mdtExportedType:
712 ulCount = m_pStgdb->m_MiniMd.getCountExportedTypes();
713 break;
714 case mdtManifestResource:
715 ulCount = m_pStgdb->m_MiniMd.getCountManifestResources();
716 break;
717 case mdtGenericParam:
718 ulCount = m_pStgdb->m_MiniMd.getCountGenericParams();
719 break;
720 case mdtGenericParamConstraint:
721 ulCount = m_pStgdb->m_MiniMd.getCountGenericParamConstraints();
722 break;
723 case mdtMethodSpec:
724 ulCount = m_pStgdb->m_MiniMd.getCountMethodSpecs();
725 break;
726 default:
727#ifdef _DEBUG
728 if(REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AssertOnBadImageFormat, 1))
729 _ASSERTE(!"Invalid Blob Offset");
730#endif
731 ulCount = 0;
732 break;
733 }
734
735ErrExit:
736
737 return ulCount;
738} // MDInternalRW::GetCountWithTokenKind
739#endif //!DACCESS_COMPILE
740
741
742//*******************************************************************************
743// Enumerator helpers
744//*******************************************************************************
745
746
747//*****************************************************************************
748// enumerator init for typedef
749//*****************************************************************************
750__checkReturn
751HRESULT MDInternalRW::EnumTypeDefInit( // return hresult
752 HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
753{
754 HRESULT hr = NOERROR;
755 LOCKREAD();
756
757 _ASSERTE(phEnum);
758
759 memset(phEnum, 0, sizeof(HENUMInternal));
760 phEnum->m_tkKind = mdtTypeDef;
761
762 if ( m_pStgdb->m_MiniMd.HasDelete() )
763 {
764 HENUMInternal::InitDynamicArrayEnum(phEnum);
765
766 phEnum->m_tkKind = mdtTypeDef;
767 for (ULONG index = 2; index <= m_pStgdb->m_MiniMd.getCountTypeDefs(); index ++ )
768 {
769 TypeDefRec *pTypeDefRec;
770 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(index, &pTypeDefRec));
771 LPCSTR szTypeDefName;
772 IfFailGo(m_pStgdb->m_MiniMd.getNameOfTypeDef(pTypeDefRec, &szTypeDefName));
773 if (IsDeletedName(szTypeDefName))
774 {
775 continue;
776 }
777 IfFailGo( HENUMInternal::AddElementToEnum(
778 phEnum,
779 TokenFromRid(index, mdtTypeDef) ) );
780 }
781 }
782 else
783 {
784 phEnum->m_EnumType = MDSimpleEnum;
785 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountTypeDefs();
786
787 // Skip over the global model typedef
788 //
789 // phEnum->u.m_ulCur : the current rid that is not yet enumerated
790 // phEnum->u.m_ulStart : the first rid that will be returned by enumerator
791 // phEnum->u.m_ulEnd : the last rid that will be returned by enumerator
792 phEnum->u.m_ulStart = phEnum->u.m_ulCur = 2;
793 phEnum->u.m_ulEnd = phEnum->m_ulCount + 1;
794 if (phEnum->m_ulCount > 0)
795 phEnum->m_ulCount --;
796 }
797ErrExit:
798
799 return hr;
800} // MDInternalRW::EnumTypeDefInit
801
802
803//*****************************************************************************
804// get the number of typedef in a scope
805//*****************************************************************************
806ULONG MDInternalRW::EnumTypeDefGetCount(
807 HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
808{
809 _ASSERTE(phEnum->m_tkKind == mdtTypeDef);
810 return phEnum->m_ulCount;
811} // MDInternalRW::EnumTypeDefGetCount
812
813
814//*****************************************************************************
815// enumerator for typedef
816//*****************************************************************************
817bool MDInternalRW::EnumTypeDefNext( // return hresult
818 HENUMInternal *phEnum, // [IN] input enum
819 mdTypeDef *ptd) // [OUT] return token
820{
821 return EnumNext(
822 phEnum,
823 ptd);
824} // MDInternalRW::EnumTypeDefNext
825
826
827//*****************************************
828// Reset the enumerator to the beginning.
829//*****************************************
830void MDInternalRW::EnumTypeDefReset(
831 HENUMInternal *phEnum) // [IN] the enumerator to be reset
832{
833 EnumReset(phEnum);
834} // MDInternalRW::EnumTypeDefReset
835
836
837//*****************************************
838// Close the enumerator. Only for read/write mode that we need to close the cursor.
839// Hopefully with readonly mode, it will be a no-op
840//*****************************************
841void MDInternalRW::EnumTypeDefClose(
842 HENUMInternal *phEnum) // [IN] the enumerator to be closed
843{
844 EnumClose(phEnum);
845} // MDInternalRW::EnumTypeDefClose
846
847#ifndef DACCESS_COMPILE
848//*****************************************************************************
849// enumerator init for MethodImpl
850//*****************************************************************************
851__checkReturn
852HRESULT MDInternalRW::EnumMethodImplInit( // return hresult
853 mdTypeDef td, // [IN] TypeDef over which to scope the enumeration.
854 HENUMInternal *phEnumBody, // [OUT] buffer to fill for enumerator data for MethodBody tokens.
855 HENUMInternal *phEnumDecl) // [OUT] buffer to fill for enumerator data for MethodDecl tokens.
856{
857 HRESULT hr = NOERROR;
858 int ridCur;
859 mdToken tkMethodBody;
860 mdToken tkMethodDecl;
861 MethodImplRec *pRec;
862 HENUMInternal hEnum;
863
864 LOCKREAD();
865
866 _ASSERTE(TypeFromToken(td) == mdtTypeDef && !IsNilToken(td));
867 _ASSERTE(phEnumBody && phEnumDecl);
868
869 memset(phEnumBody, 0, sizeof(HENUMInternal));
870 memset(phEnumDecl, 0, sizeof(HENUMInternal));
871 memset(&hEnum, 0, sizeof(HENUMInternal));
872
873 HENUMInternal::InitDynamicArrayEnum(phEnumBody);
874 HENUMInternal::InitDynamicArrayEnum(phEnumDecl);
875
876 phEnumBody->m_tkKind = (TBL_MethodImpl << 24);
877 phEnumDecl->m_tkKind = (TBL_MethodImpl << 24);
878
879 // Get the range of rids.
880 IfFailGo( m_pStgdb->m_MiniMd.FindMethodImplHelper(td, &hEnum) );
881
882 while (HENUMInternal::EnumNext(&hEnum, (mdToken *)&ridCur))
883 {
884 // Get the MethodBody and MethodDeclaration tokens for the current
885 // MethodImpl record.
886 IfFailGo(m_pStgdb->m_MiniMd.GetMethodImplRecord(ridCur, &pRec));
887 tkMethodBody = m_pStgdb->m_MiniMd.getMethodBodyOfMethodImpl(pRec);
888 tkMethodDecl = m_pStgdb->m_MiniMd.getMethodDeclarationOfMethodImpl(pRec);
889
890 // Add the Method body/declaration pairs to the Enum
891 IfFailGo( HENUMInternal::AddElementToEnum(phEnumBody, tkMethodBody ) );
892 IfFailGo( HENUMInternal::AddElementToEnum(phEnumDecl, tkMethodDecl ) );
893 }
894ErrExit:
895 HENUMInternal::ClearEnum(&hEnum);
896 return hr;
897} // MDInternalRW::EnumMethodImplInit
898
899//*****************************************************************************
900// get the number of MethodImpls in a scope
901//*****************************************************************************
902ULONG MDInternalRW::EnumMethodImplGetCount(
903 HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
904 HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
905{
906 _ASSERTE((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl &&
907 (phEnumDecl->m_tkKind >> 24) == TBL_MethodImpl);
908 _ASSERTE(phEnumBody->m_EnumType == MDDynamicArrayEnum &&
909 phEnumDecl->m_EnumType == MDDynamicArrayEnum);
910 _ASSERTE(phEnumBody->m_ulCount == phEnumDecl->m_ulCount);
911
912 return phEnumBody->m_ulCount;
913} // MDInternalRW::EnumMethodImplGetCount
914
915
916//*****************************************************************************
917// enumerator for MethodImpl.
918//*****************************************************************************
919__checkReturn
920HRESULT
921MDInternalRW::EnumMethodImplNext( // return hresult
922 HENUMInternal *phEnumBody, // [IN] input enum for MethodBody
923 HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl
924 mdToken *ptkBody, // [OUT] return token for MethodBody
925 mdToken *ptkDecl) // [OUT] return token for MethodDecl
926{
927 _ASSERTE((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl &&
928 (phEnumDecl->m_tkKind >> 24) == TBL_MethodImpl);
929 _ASSERTE(phEnumBody->m_EnumType == MDDynamicArrayEnum &&
930 phEnumDecl->m_EnumType == MDDynamicArrayEnum);
931 _ASSERTE(phEnumBody->m_ulCount == phEnumDecl->m_ulCount);
932 _ASSERTE(ptkBody && ptkDecl);
933
934 EnumNext(phEnumBody, ptkBody);
935 return EnumNext(phEnumDecl, ptkDecl) ? S_OK : S_FALSE;
936} // MDInternalRW::EnumMethodImplNext
937
938//*****************************************
939// Reset the enumerator to the beginning.
940//*****************************************
941void MDInternalRW::EnumMethodImplReset(
942 HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
943 HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
944{
945 _ASSERTE((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl &&
946 (phEnumDecl->m_tkKind >> 24) == TBL_MethodImpl);
947 _ASSERTE(phEnumBody->m_EnumType == MDDynamicArrayEnum &&
948 phEnumDecl->m_EnumType == MDDynamicArrayEnum);
949 _ASSERTE(phEnumBody->m_ulCount == phEnumDecl->m_ulCount);
950
951 EnumReset(phEnumBody);
952 EnumReset(phEnumDecl);
953} // MDInternalRW::EnumMethodImplReset
954
955
956//*****************************************
957// Close the enumerator.
958//*****************************************
959void MDInternalRW::EnumMethodImplClose(
960 HENUMInternal *phEnumBody, // [IN] MethodBody enumerator.
961 HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator.
962{
963 _ASSERTE((phEnumBody->m_tkKind >> 24) == TBL_MethodImpl &&
964 (phEnumDecl->m_tkKind >> 24) == TBL_MethodImpl);
965 _ASSERTE(phEnumBody->m_EnumType == MDDynamicArrayEnum &&
966 phEnumDecl->m_EnumType == MDDynamicArrayEnum);
967 _ASSERTE(phEnumBody->m_ulCount == phEnumDecl->m_ulCount);
968
969 EnumClose(phEnumBody);
970 EnumClose(phEnumDecl);
971} // MDInternalRW::EnumMethodImplClose
972#endif //!DACCESS_COMPILE
973
974//******************************************************************************
975// enumerator for global functions
976//******************************************************************************
977__checkReturn
978HRESULT MDInternalRW::EnumGlobalFunctionsInit( // return hresult
979 HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
980{
981 return EnumInit(mdtMethodDef, m_tdModule, phEnum);
982} // MDInternalRW::EnumGlobalFunctionsInit
983
984
985//******************************************************************************
986// enumerator for global fields
987//******************************************************************************
988__checkReturn
989HRESULT MDInternalRW::EnumGlobalFieldsInit( // return hresult
990 HENUMInternal *phEnum) // [OUT] buffer to fill for enumerator data
991{
992 return EnumInit(mdtFieldDef, m_tdModule, phEnum);
993} // MDInternalRW::EnumGlobalFieldsInit
994
995
996#ifdef _PREFAST_
997#pragma warning(push)
998#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
999#endif
1000//*****************************************
1001// Enumerator initializer
1002//*****************************************
1003__checkReturn
1004HRESULT MDInternalRW::EnumInit( // return S_FALSE if record not found
1005 DWORD tkKind, // [IN] which table to work on
1006 mdToken tkParent, // [IN] token to scope the search
1007 HENUMInternal *phEnum) // [OUT] the enumerator to fill
1008{
1009 HRESULT hr = S_OK;
1010 ULONG ulStart, ulEnd, ulMax;
1011 ULONG index;
1012 LOCKREAD();
1013
1014 // Vars for query.
1015 _ASSERTE(phEnum);
1016 memset(phEnum, 0, sizeof(HENUMInternal));
1017
1018 // cache the tkKind and the scope
1019 phEnum->m_tkKind = TypeFromToken(tkKind);
1020
1021 TypeDefRec *pRec;
1022
1023 phEnum->m_EnumType = MDSimpleEnum;
1024
1025 switch (TypeFromToken(tkKind))
1026 {
1027 case mdtFieldDef:
1028 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(tkParent), &pRec));
1029 ulStart = m_pStgdb->m_MiniMd.getFieldListOfTypeDef(pRec);
1030 IfFailGo(m_pStgdb->m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(tkParent), &ulEnd));
1031 if ( m_pStgdb->m_MiniMd.HasDelete() )
1032 {
1033 HENUMInternal::InitDynamicArrayEnum(phEnum);
1034 for (index = ulStart; index < ulEnd; index ++ )
1035 {
1036 FieldRec *pFieldRec;
1037 RID fieldRid;
1038 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRid(index, &fieldRid));
1039 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(index, &pFieldRec));
1040 LPCSTR szFieldName;
1041 IfFailGo(m_pStgdb->m_MiniMd.getNameOfField(pFieldRec, &szFieldName));
1042 if (IsFdRTSpecialName(pFieldRec->GetFlags()) && IsDeletedName(szFieldName) )
1043 {
1044 continue;
1045 }
1046 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRid(index, &fieldRid));
1047 IfFailGo(HENUMInternal::AddElementToEnum(
1048 phEnum,
1049 TokenFromRid(fieldRid, mdtFieldDef)));
1050 }
1051 }
1052 else if (m_pStgdb->m_MiniMd.HasIndirectTable(TBL_Field))
1053 {
1054 HENUMInternal::InitDynamicArrayEnum(phEnum);
1055 for (index = ulStart; index < ulEnd; index ++ )
1056 {
1057 RID fieldRid;
1058 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRid(index, &fieldRid));
1059 IfFailGo(HENUMInternal::AddElementToEnum(
1060 phEnum,
1061 TokenFromRid(fieldRid, mdtFieldDef)));
1062 }
1063 }
1064 else
1065 {
1066 HENUMInternal::InitSimpleEnum( mdtFieldDef, ulStart, ulEnd, phEnum);
1067 }
1068 break;
1069
1070 case mdtMethodDef:
1071 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(tkParent), &pRec));
1072 ulStart = m_pStgdb->m_MiniMd.getMethodListOfTypeDef(pRec);
1073 IfFailGo(m_pStgdb->m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(tkParent), &ulEnd));
1074 if ( m_pStgdb->m_MiniMd.HasDelete() )
1075 {
1076 HENUMInternal::InitDynamicArrayEnum(phEnum);
1077 for (index = ulStart; index < ulEnd; index ++ )
1078 {
1079 MethodRec *pMethodRec;
1080 RID methodRid;
1081 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRid(index, &methodRid));
1082 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(methodRid, &pMethodRec));
1083 LPCSTR szMethodName;
1084 IfFailGo(m_pStgdb->m_MiniMd.getNameOfMethod(pMethodRec, &szMethodName));
1085 if (IsMdRTSpecialName(pMethodRec->GetFlags()) && IsDeletedName(szMethodName))
1086 {
1087 continue;
1088 }
1089 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRid(index, &methodRid));
1090 IfFailGo(HENUMInternal::AddElementToEnum(
1091 phEnum,
1092 TokenFromRid(methodRid, mdtMethodDef)));
1093 }
1094 }
1095 else if (m_pStgdb->m_MiniMd.HasIndirectTable(TBL_Method))
1096 {
1097 HENUMInternal::InitDynamicArrayEnum(phEnum);
1098 for (index = ulStart; index < ulEnd; index ++ )
1099 {
1100 RID methodRid;
1101 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRid(index, &methodRid));
1102 IfFailGo(HENUMInternal::AddElementToEnum(
1103 phEnum,
1104 TokenFromRid(methodRid, mdtMethodDef)));
1105 }
1106 }
1107 else
1108 {
1109 HENUMInternal::InitSimpleEnum( mdtMethodDef, ulStart, ulEnd, phEnum);
1110 }
1111 break;
1112
1113 case mdtInterfaceImpl:
1114 if (!m_pStgdb->m_MiniMd.IsSorted(TBL_InterfaceImpl) && !m_pStgdb->m_MiniMd.IsTableVirtualSorted(TBL_InterfaceImpl))
1115 {
1116 // virtual sort table will be created!
1117 //
1118 CONVERT_READ_TO_WRITE_LOCK();
1119 }
1120
1121 IfFailGo( m_pStgdb->m_MiniMd.GetInterfaceImplsForTypeDef(RidFromToken(tkParent), &ulStart, &ulEnd) );
1122 if ( m_pStgdb->m_MiniMd.IsSorted( TBL_InterfaceImpl ) )
1123 {
1124 // These are index to InterfaceImpl table directly
1125 HENUMInternal::InitSimpleEnum( mdtInterfaceImpl, ulStart, ulEnd, phEnum);
1126 }
1127 else
1128 {
1129 // These are index to VirtualSort table. Skip over one level direction.
1130 HENUMInternal::InitDynamicArrayEnum(phEnum);
1131 for (index = ulStart; index < ulEnd; index ++ )
1132 {
1133 IfFailGo( HENUMInternal::AddElementToEnum(
1134 phEnum,
1135 TokenFromRid(m_pStgdb->m_MiniMd.GetInterfaceImplRid(index), mdtInterfaceImpl) ) );
1136 }
1137 }
1138 break;
1139
1140 case mdtGenericParam:
1141 //@todo: deal with non-sorted case.
1142
1143 if (TypeFromToken(tkParent) == mdtTypeDef)
1144 {
1145 IfFailGo(m_pStgdb->m_MiniMd.getGenericParamsForTypeDef(
1146 RidFromToken(tkParent),
1147 &phEnum->u.m_ulEnd,
1148 &(phEnum->u.m_ulStart)));
1149 }
1150 else
1151 {
1152 IfFailGo(m_pStgdb->m_MiniMd.getGenericParamsForMethodDef(
1153 RidFromToken(tkParent),
1154 &phEnum->u.m_ulEnd,
1155 &(phEnum->u.m_ulStart)));
1156 }
1157 break;
1158
1159 case mdtGenericParamConstraint:
1160 if ( !m_pStgdb->m_MiniMd.IsSorted(TBL_GenericParamConstraint) && !m_pStgdb->m_MiniMd.IsTableVirtualSorted(TBL_GenericParamConstraint))
1161 {
1162 // virtual sort table will be created!
1163 //
1164 CONVERT_READ_TO_WRITE_LOCK();
1165 }
1166
1167 IfFailGo( m_pStgdb->m_MiniMd.GetGenericParamConstraintsForToken(RidFromToken(tkParent), &ulStart, &ulEnd) );
1168 if ( m_pStgdb->m_MiniMd.IsSorted( TBL_GenericParamConstraint ) )
1169 {
1170 // These are index to GenericParamConstraint table directly
1171 HENUMInternal::InitSimpleEnum( mdtGenericParamConstraint, ulStart, ulEnd, phEnum);
1172 }
1173 else
1174 {
1175 // These are index to VirtualSort table. Skip over one level direction.
1176 HENUMInternal::InitDynamicArrayEnum(phEnum);
1177 for (index = ulStart; index < ulEnd; index ++ )
1178 {
1179 IfFailGo( HENUMInternal::AddElementToEnum(
1180 phEnum,
1181 TokenFromRid(m_pStgdb->m_MiniMd.GetGenericParamConstraintRid(index), mdtGenericParamConstraint) ) );
1182 }
1183 }
1184 break;
1185
1186 case mdtProperty:
1187 RID ridPropertyMap;
1188 PropertyMapRec *pPropertyMapRec;
1189
1190 // get the starting/ending rid of properties of this typedef
1191 IfFailGo(m_pStgdb->m_MiniMd.FindPropertyMapFor(RidFromToken(tkParent), &ridPropertyMap));
1192 if (!InvalidRid(ridPropertyMap))
1193 {
1194 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pPropertyMapRec));
1195 ulStart = m_pStgdb->m_MiniMd.getPropertyListOfPropertyMap(pPropertyMapRec);
1196 IfFailGo(m_pStgdb->m_MiniMd.getEndPropertyListOfPropertyMap(ridPropertyMap, &ulEnd));
1197 ulMax = m_pStgdb->m_MiniMd.getCountPropertys() + 1;
1198 if(ulStart == 0) ulStart = 1;
1199 if(ulEnd > ulMax) ulEnd = ulMax;
1200 if(ulStart > ulEnd) ulStart = ulEnd;
1201 if ( m_pStgdb->m_MiniMd.HasDelete() )
1202 {
1203 HENUMInternal::InitDynamicArrayEnum(phEnum);
1204 for (index = ulStart; index < ulEnd; index ++ )
1205 {
1206 PropertyRec *pPropertyRec;
1207 RID propertyRid;
1208 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRid(index, &propertyRid));
1209 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRecord(
1210 propertyRid,
1211 &pPropertyRec));
1212 LPCSTR szPropertyName;
1213 IfFailGo(m_pStgdb->m_MiniMd.getNameOfProperty(pPropertyRec, &szPropertyName));
1214 if (IsPrRTSpecialName(pPropertyRec->GetPropFlags()) && IsDeletedName(szPropertyName))
1215 {
1216 continue;
1217 }
1218 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRid(index, &propertyRid));
1219 IfFailGo(HENUMInternal::AddElementToEnum(
1220 phEnum,
1221 TokenFromRid(propertyRid, mdtProperty)));
1222 }
1223 }
1224 else if (m_pStgdb->m_MiniMd.HasIndirectTable(TBL_Property))
1225 {
1226 HENUMInternal::InitDynamicArrayEnum(phEnum);
1227 for (index = ulStart; index < ulEnd; index ++ )
1228 {
1229 RID propertyRid;
1230 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRid(index, &propertyRid));
1231 IfFailGo(HENUMInternal::AddElementToEnum(
1232 phEnum,
1233 TokenFromRid(propertyRid, mdtProperty)));
1234 }
1235 }
1236 else
1237 {
1238 HENUMInternal::InitSimpleEnum( mdtProperty, ulStart, ulEnd, phEnum);
1239 }
1240 }
1241 break;
1242
1243 case mdtEvent:
1244 RID ridEventMap;
1245 EventMapRec *pEventMapRec;
1246
1247 // get the starting/ending rid of events of this typedef
1248 IfFailGo(m_pStgdb->m_MiniMd.FindEventMapFor(RidFromToken(tkParent), &ridEventMap));
1249 if (!InvalidRid(ridEventMap))
1250 {
1251 IfFailGo(m_pStgdb->m_MiniMd.GetEventMapRecord(ridEventMap, &pEventMapRec));
1252 ulStart = m_pStgdb->m_MiniMd.getEventListOfEventMap(pEventMapRec);
1253 IfFailGo(m_pStgdb->m_MiniMd.getEndEventListOfEventMap(ridEventMap, &ulEnd));
1254 ulMax = m_pStgdb->m_MiniMd.getCountEvents() + 1;
1255 if(ulStart == 0) ulStart = 1;
1256 if(ulEnd > ulMax) ulEnd = ulMax;
1257 if(ulStart > ulEnd) ulStart = ulEnd;
1258 if ( m_pStgdb->m_MiniMd.HasDelete() )
1259 {
1260 HENUMInternal::InitDynamicArrayEnum(phEnum);
1261 for (index = ulStart; index < ulEnd; index ++ )
1262 {
1263 EventRec *pEventRec;
1264 RID eventRid;
1265 IfFailGo(m_pStgdb->m_MiniMd.GetEventRid(index, &eventRid));
1266 IfFailGo(m_pStgdb->m_MiniMd.GetEventRecord(eventRid, &pEventRec));
1267 LPCSTR szEventName;
1268 IfFailGo(m_pStgdb->m_MiniMd.getNameOfEvent(pEventRec, &szEventName));
1269 if (IsEvRTSpecialName(pEventRec->GetEventFlags()) && IsDeletedName(szEventName))
1270 {
1271 continue;
1272 }
1273 IfFailGo(m_pStgdb->m_MiniMd.GetEventRid(index, &eventRid));
1274 IfFailGo(HENUMInternal::AddElementToEnum(
1275 phEnum,
1276 TokenFromRid(eventRid, mdtEvent)));
1277 }
1278 }
1279 else if (m_pStgdb->m_MiniMd.HasIndirectTable(TBL_Event))
1280 {
1281 HENUMInternal::InitDynamicArrayEnum(phEnum);
1282 for (index = ulStart; index < ulEnd; index ++ )
1283 {
1284 RID eventRid;
1285 IfFailGo(m_pStgdb->m_MiniMd.GetEventRid(index, &eventRid));
1286 IfFailGo( HENUMInternal::AddElementToEnum(
1287 phEnum,
1288 TokenFromRid(eventRid, mdtEvent) ) );
1289 }
1290 }
1291 else
1292 {
1293 HENUMInternal::InitSimpleEnum( mdtEvent, ulStart, ulEnd, phEnum);
1294 }
1295 }
1296 break;
1297
1298 case mdtParamDef:
1299 _ASSERTE(TypeFromToken(tkParent) == mdtMethodDef);
1300
1301 MethodRec *pMethodRec;
1302 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(tkParent), &pMethodRec));
1303
1304 // figure out the start rid and end rid of the parameter list of this methoddef
1305 ulStart = m_pStgdb->m_MiniMd.getParamListOfMethod(pMethodRec);
1306 IfFailGo(m_pStgdb->m_MiniMd.getEndParamListOfMethod(RidFromToken(tkParent), &ulEnd));
1307 if (m_pStgdb->m_MiniMd.HasIndirectTable(TBL_Param))
1308 {
1309 HENUMInternal::InitDynamicArrayEnum(phEnum);
1310 for (index = ulStart; index < ulEnd; index ++ )
1311 {
1312 RID paramRid;
1313 IfFailGo(m_pStgdb->m_MiniMd.GetParamRid(index, &paramRid));
1314 IfFailGo(HENUMInternal::AddElementToEnum(
1315 phEnum,
1316 TokenFromRid(paramRid, mdtParamDef)));
1317 }
1318 }
1319 else
1320 {
1321 HENUMInternal::InitSimpleEnum( mdtParamDef, ulStart, ulEnd, phEnum);
1322 }
1323 break;
1324
1325 case mdtCustomAttribute:
1326 if (!m_pStgdb->m_MiniMd.IsSorted(TBL_CustomAttribute) && !m_pStgdb->m_MiniMd.IsTableVirtualSorted(TBL_CustomAttribute))
1327 {
1328 // CA's map table table will be sorted!
1329 //
1330 CONVERT_READ_TO_WRITE_LOCK();
1331 }
1332
1333 IfFailGo( m_pStgdb->m_MiniMd.GetCustomAttributeForToken(tkParent, &ulStart, &ulEnd) );
1334 if ( m_pStgdb->m_MiniMd.IsSorted( TBL_CustomAttribute ) )
1335 {
1336 // These are index to CustomAttribute table directly
1337 HENUMInternal::InitSimpleEnum( mdtCustomAttribute, ulStart, ulEnd, phEnum);
1338 }
1339 else
1340 {
1341 // These are index to VirtualSort table. Skip over one level direction.
1342 HENUMInternal::InitDynamicArrayEnum(phEnum);
1343 for (index = ulStart; index < ulEnd; index ++ )
1344 {
1345 IfFailGo( HENUMInternal::AddElementToEnum(
1346 phEnum,
1347 TokenFromRid(m_pStgdb->m_MiniMd.GetCustomAttributeRid(index), mdtCustomAttribute) ) );
1348 }
1349 }
1350 break;
1351 case mdtAssemblyRef:
1352 _ASSERTE(IsNilToken(tkParent));
1353 phEnum->u.m_ulStart = 1;
1354 phEnum->u.m_ulEnd = m_pStgdb->m_MiniMd.getCountAssemblyRefs() + 1;
1355 break;
1356 case mdtFile:
1357 _ASSERTE(IsNilToken(tkParent));
1358 phEnum->u.m_ulStart = 1;
1359 phEnum->u.m_ulEnd = m_pStgdb->m_MiniMd.getCountFiles() + 1;
1360 break;
1361 case mdtExportedType:
1362 _ASSERTE(IsNilToken(tkParent));
1363 if ( m_pStgdb->m_MiniMd.HasDelete() )
1364 {
1365 HENUMInternal::InitDynamicArrayEnum(phEnum);
1366
1367 phEnum->m_tkKind = mdtExportedType;
1368 for (ULONG typeindex = 1; typeindex <= m_pStgdb->m_MiniMd.getCountExportedTypes(); typeindex ++ )
1369 {
1370 ExportedTypeRec *pExportedTypeRec;
1371 IfFailGo(m_pStgdb->m_MiniMd.GetExportedTypeRecord(typeindex, &pExportedTypeRec));
1372 LPCSTR szTypeName;
1373 IfFailGo(m_pStgdb->m_MiniMd.getTypeNameOfExportedType(pExportedTypeRec, &szTypeName));
1374 if (IsDeletedName(szTypeName))
1375 {
1376 continue;
1377 }
1378 IfFailGo( HENUMInternal::AddElementToEnum(
1379 phEnum,
1380 TokenFromRid(typeindex, mdtExportedType) ) );
1381 }
1382 }
1383 else
1384 {
1385 phEnum->u.m_ulStart = 1;
1386 phEnum->u.m_ulEnd = m_pStgdb->m_MiniMd.getCountExportedTypes() + 1;
1387 }
1388 break;
1389 case mdtManifestResource:
1390 _ASSERTE(IsNilToken(tkParent));
1391 phEnum->u.m_ulStart = 1;
1392 phEnum->u.m_ulEnd = m_pStgdb->m_MiniMd.getCountManifestResources() + 1;
1393 break;
1394 case mdtModuleRef:
1395 _ASSERTE(IsNilToken(tkParent));
1396 phEnum->u.m_ulStart = 1;
1397 phEnum->u.m_ulEnd = m_pStgdb->m_MiniMd.getCountModuleRefs() + 1;
1398 break;
1399 default:
1400 _ASSERTE(!"ENUM INIT not implemented for the uncompressed format!");
1401 IfFailGo(E_NOTIMPL);
1402 break;
1403 }
1404
1405 // If the count is negative, the metadata is corrupted somehow.
1406 if (phEnum->u.m_ulEnd < phEnum->u.m_ulStart)
1407 IfFailGo(CLDB_E_FILE_CORRUPT);
1408
1409 phEnum->m_ulCount = phEnum->u.m_ulEnd - phEnum->u.m_ulStart;
1410 phEnum->u.m_ulCur = phEnum->u.m_ulStart;
1411ErrExit:
1412 // we are done
1413
1414 return hr;
1415} // MDInternalRW::EnumInit
1416#ifdef _PREFAST_
1417#pragma warning(pop)
1418#endif
1419
1420//*****************************************
1421// Enumerator initializer
1422//*****************************************
1423__checkReturn
1424HRESULT MDInternalRW::EnumAllInit( // return S_FALSE if record not found
1425 DWORD tkKind, // [IN] which table to work on
1426 HENUMInternal *phEnum) // [OUT] the enumerator to fill
1427{
1428 HRESULT hr = S_OK;
1429 LOCKREAD();
1430
1431 // Vars for query.
1432 _ASSERTE(phEnum);
1433 memset(phEnum, 0, sizeof(HENUMInternal));
1434
1435 // cache the tkKind and the scope
1436 phEnum->m_tkKind = TypeFromToken(tkKind);
1437 phEnum->m_EnumType = MDSimpleEnum;
1438
1439 switch (TypeFromToken(tkKind))
1440 {
1441 case mdtTypeRef:
1442 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountTypeRefs();
1443 break;
1444
1445 case mdtMemberRef:
1446 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountMemberRefs();
1447 break;
1448
1449 case mdtSignature:
1450 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountStandAloneSigs();
1451 break;
1452
1453 case mdtMethodDef:
1454 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountMethods();
1455 break;
1456
1457 case mdtMethodSpec:
1458 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountMethodSpecs();
1459 break;
1460
1461 case mdtFieldDef:
1462 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountFields();
1463 break;
1464
1465 case mdtTypeSpec:
1466 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountTypeSpecs();
1467 break;
1468
1469 case mdtAssemblyRef:
1470 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountAssemblyRefs();
1471 break;
1472
1473 case mdtModuleRef:
1474 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountModuleRefs();
1475 break;
1476
1477 case mdtTypeDef:
1478 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountTypeDefs();
1479 break;
1480
1481 case mdtFile:
1482 phEnum->m_ulCount = m_pStgdb->m_MiniMd.getCountFiles();
1483 break;
1484
1485 default:
1486 _ASSERTE(!"Bad token kind!");
1487 break;
1488 }
1489 phEnum->u.m_ulStart = phEnum->u.m_ulCur = 1;
1490 phEnum->u.m_ulEnd = phEnum->m_ulCount + 1;
1491
1492ErrExit:
1493 // we are done
1494
1495 return hr;
1496} // MDInternalRW::EnumAllInit
1497
1498
1499//*****************************************
1500// get the count
1501//*****************************************
1502ULONG MDInternalRW::EnumGetCount(
1503 HENUMInternal *phEnum) // [IN] the enumerator to retrieve information
1504{
1505 _ASSERTE(phEnum);
1506 return phEnum->m_ulCount;
1507} // MDInternalRW::EnumGetCount
1508
1509//*****************************************
1510// Get next value contained in the enumerator
1511//*****************************************
1512bool MDInternalRW::EnumNext(
1513 HENUMInternal *phEnum, // [IN] the enumerator to retrieve information
1514 mdToken *ptk) // [OUT] token to scope the search
1515{
1516 _ASSERTE(phEnum && ptk);
1517 if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd)
1518 return false;
1519
1520 if ( phEnum->m_EnumType == MDSimpleEnum )
1521 {
1522 *ptk = phEnum->u.m_ulCur | phEnum->m_tkKind;
1523 phEnum->u.m_ulCur++;
1524 }
1525 else
1526 {
1527 TOKENLIST *pdalist = (TOKENLIST *)&(phEnum->m_cursor);
1528
1529 _ASSERTE( phEnum->m_EnumType == MDDynamicArrayEnum );
1530 *ptk = *( pdalist->Get(phEnum->u.m_ulCur++) );
1531 }
1532 return true;
1533} // MDInternalRW::EnumNext
1534
1535
1536//*****************************************
1537// Reset the enumerator to the beginning.
1538//*****************************************
1539void MDInternalRW::EnumReset(
1540 HENUMInternal *phEnum) // [IN] the enumerator to be reset
1541{
1542 _ASSERTE(phEnum);
1543 _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || phEnum->m_EnumType == MDDynamicArrayEnum);
1544
1545 phEnum->u.m_ulCur = phEnum->u.m_ulStart;
1546} // MDInternalRW::EnumReset
1547
1548
1549//*****************************************
1550// Close the enumerator. Only for read/write mode that we need to close the cursor.
1551// Hopefully with readonly mode, it will be a no-op
1552//*****************************************
1553void MDInternalRW::EnumClose(
1554 HENUMInternal *phEnum) // [IN] the enumerator to be closed
1555{
1556 _ASSERTE( phEnum->m_EnumType == MDSimpleEnum ||
1557 phEnum->m_EnumType == MDDynamicArrayEnum ||
1558 phEnum->m_EnumType == MDCustomEnum );
1559 if (phEnum->m_EnumType == MDDynamicArrayEnum)
1560 HENUMInternal::ClearEnum(phEnum);
1561} // MDInternalRW::EnumClose
1562
1563
1564#ifndef DACCESS_COMPILE
1565//---------------------------------------------------------------------------------------
1566//
1567// Initialize enumerator of PermissionSets.
1568//
1569// Return Value:
1570// CLDB_E_RECORD_NOTFOUND ... If record not found.
1571// S_OK and empty enumeration ... If tkParent is nil token and Action is dclActionNil.
1572//
1573__checkReturn
1574HRESULT
1575MDInternalRW::EnumPermissionSetsInit(
1576 mdToken tkParent, // [IN] Token to scope the search.
1577 CorDeclSecurity Action, // [IN] Action to scope the search.
1578 HENUMInternal *phEnum) // [OUT] Enumerator to fill.
1579{
1580 HRESULT hr = S_OK;
1581 DeclSecurityRec *pDecl;
1582 RID ridCur;
1583 RID ridEnd;
1584
1585 LOCKREAD();
1586
1587 _ASSERTE(phEnum != NULL);
1588
1589 phEnum->m_EnumType = MDSimpleEnum;
1590
1591 if (!m_pStgdb->m_MiniMd.IsSorted(TBL_DeclSecurity) && !m_pStgdb->m_MiniMd.IsTableVirtualSorted(TBL_DeclSecurity))
1592 {
1593 // DeclSecurity lookup table might be created!
1594 CONVERT_READ_TO_WRITE_LOCK();
1595 }
1596
1597 // This call requires write-lock if the table is not sorted and doesn't have VirtualSort:
1598 IfFailGo(m_pStgdb->m_MiniMd.GetDeclSecurityForToken(tkParent, &ridCur, &ridEnd));
1599 if (m_pStgdb->m_MiniMd.IsSorted(TBL_DeclSecurity))
1600 {
1601 // These are index to DeclSecurity table directly
1602 if (Action != dclActionNil)
1603 {
1604 for (; ridCur < ridEnd; ridCur++)
1605 {
1606 IfFailGo(m_pStgdb->m_MiniMd.GetDeclSecurityRecord(ridCur, &pDecl));
1607 if (Action == m_pStgdb->m_MiniMd.getActionOfDeclSecurity(pDecl))
1608 {
1609 // found a match
1610 HENUMInternal::InitSimpleEnum(mdtPermission, ridCur, ridCur + 1, phEnum);
1611 goto ErrExit;
1612 }
1613 }
1614 hr = CLDB_E_RECORD_NOTFOUND;
1615 }
1616 else
1617 {
1618 HENUMInternal::InitSimpleEnum(mdtPermission, ridCur, ridEnd, phEnum);
1619 }
1620 }
1621 else
1622 {
1623 // These are index to VirtualSort table. Skip over one level direction.
1624 if (Action != dclActionNil)
1625 {
1626 RID ridActual;
1627
1628 for (; ridCur < ridEnd; ridCur++)
1629 {
1630 ridActual = m_pStgdb->m_MiniMd.GetDeclSecurityRid(ridCur);
1631 IfFailGo(m_pStgdb->m_MiniMd.GetDeclSecurityRecord(ridActual, &pDecl));
1632 if (Action == m_pStgdb->m_MiniMd.getActionOfDeclSecurity(pDecl))
1633 {
1634 // found a match
1635 HENUMInternal::InitSimpleEnum(mdtPermission, ridActual, ridActual + 1, phEnum);
1636 goto ErrExit;
1637 }
1638 }
1639 hr = CLDB_E_RECORD_NOTFOUND;
1640 }
1641 else
1642 {
1643 HENUMInternal::InitDynamicArrayEnum(phEnum);
1644 for (; ridCur < ridEnd; ridCur++)
1645 {
1646 IfFailGo(HENUMInternal::AddElementToEnum(
1647 phEnum,
1648 TokenFromRid(m_pStgdb->m_MiniMd.GetDeclSecurityRid(ridCur), mdtPermission)));
1649 }
1650 }
1651 }
1652
1653ErrExit:
1654 return hr;
1655} // MDInternalRW::EnumPermissionSetsInit
1656#endif //!DACCESS_COMPILE
1657
1658//*****************************************
1659// Enumerator initializer for CustomAttributes
1660//*****************************************
1661__checkReturn
1662HRESULT MDInternalRW::EnumCustomAttributeByNameInit(// return S_FALSE if record not found
1663 mdToken tkParent, // [IN] token to scope the search
1664 LPCSTR szName, // [IN] CustomAttribute's name to scope the search
1665 HENUMInternal *phEnum) // [OUT] the enumerator to fill
1666{
1667 return m_pStgdb->m_MiniMd.CommonEnumCustomAttributeByName(tkParent, szName, false, phEnum);
1668} // MDInternalRW::EnumCustomAttributeByNameInit
1669
1670//*****************************************
1671// Enumerator for CustomAttributes which doesn't
1672// allocate any memory
1673//*****************************************
1674__checkReturn
1675HRESULT MDInternalRW::SafeAndSlowEnumCustomAttributeByNameInit(// return S_FALSE if record not found
1676 mdToken tkParent, // [IN] token to scope the search
1677 LPCSTR szName, // [IN] CustomAttribute's name to scope the search
1678 HENUMInternal *phEnum) // [OUT] The enumerator
1679{
1680 _ASSERTE(phEnum);
1681
1682 HRESULT hr;
1683 ULONG ridStart, ridEnd; // Loop start and endpoints.
1684
1685 // Get the list of custom values for the parent object.
1686 if (m_pStgdb->m_MiniMd.IsSorted(TBL_CustomAttribute))
1687 {
1688 IfFailRet(m_pStgdb->m_MiniMd.getCustomAttributeForToken(tkParent, &ridEnd, &ridStart));
1689 // If found none, done.
1690 if (ridStart == 0)
1691 goto NoMatch;
1692 }
1693 else
1694 {
1695 // linear scan of entire table.
1696 ridEnd = m_pStgdb->m_MiniMd.getCountCustomAttributes() + 1;
1697 if (ridEnd == 1)
1698 goto NoMatch;
1699
1700 ridStart = 1;
1701 }
1702 phEnum->m_EnumType = MDCustomEnum;
1703 phEnum->m_tkKind = mdtCustomAttribute;
1704 phEnum->u.m_ulStart = ridStart;
1705 phEnum->u.m_ulEnd = ridEnd;
1706 phEnum->u.m_ulCur = ridStart;
1707
1708 return S_OK;
1709
1710NoMatch:
1711 return S_FALSE;
1712} // MDInternalRW::SafeAndSlowEnumCustomAttributeByNameInit
1713
1714__checkReturn
1715HRESULT MDInternalRW::SafeAndSlowEnumCustomAttributeByNameNext(// return S_FALSE if record not found
1716 mdToken tkParent, // [IN] token to scope the search
1717 LPCSTR szName, // [IN] CustomAttribute's name to scope the search
1718 HENUMInternal *phEnum, // [IN] The enumerator
1719 mdCustomAttribute *mdAttribute) // [OUT] The custom attribute that was found
1720{
1721 _ASSERTE(phEnum);
1722 _ASSERTE(phEnum->m_EnumType == MDCustomEnum);
1723 _ASSERTE(phEnum->m_tkKind == mdtCustomAttribute);
1724
1725 // Look for one with the given name.
1726 for (; phEnum->u.m_ulCur < phEnum->u.m_ulEnd; ++phEnum->u.m_ulCur)
1727 {
1728 if (S_OK == m_pStgdb->m_MiniMd.CompareCustomAttribute( tkParent, szName, phEnum->u.m_ulCur))
1729 {
1730 // If here, found a match.
1731 *mdAttribute = TokenFromRid(phEnum->u.m_ulCur, mdtCustomAttribute);
1732 phEnum->u.m_ulCur++;
1733 return S_OK;
1734 }
1735 }
1736 // No match...
1737 return S_FALSE;
1738}// MDInternalRW::SafeAndSlowEnumCustomAttributeByNameNext
1739
1740//*****************************************
1741// Nagivator helper to navigate back to the parent token given a token.
1742// For example, given a memberdef token, it will return the containing typedef.
1743//
1744// the mapping is as following:
1745// ---given child type---------parent type
1746// mdMethodDef mdTypeDef
1747// mdFieldDef mdTypeDef
1748// mdInterfaceImpl mdTypeDef
1749// mdParam mdMethodDef
1750// mdProperty mdTypeDef
1751// mdEvent mdTypeDef
1752//
1753//*****************************************
1754__checkReturn
1755HRESULT MDInternalRW::GetParentToken(
1756 mdToken tkChild, // [IN] given child token
1757 mdToken *ptkParent) // [OUT] returning parent
1758{
1759 HRESULT hr = NOERROR;
1760 LOCKREAD();
1761
1762 _ASSERTE(ptkParent);
1763
1764 switch (TypeFromToken(tkChild))
1765 {
1766 case mdtTypeDef:
1767 {
1768 RID rid;
1769 if (!m_pStgdb->m_MiniMd.IsSorted(TBL_NestedClass) && !m_pStgdb->m_MiniMd.IsTableVirtualSorted(TBL_NestedClass))
1770 {
1771 // NestedClass table is not sorted.
1772 CONVERT_READ_TO_WRITE_LOCK();
1773 }
1774 IfFailGo(m_pStgdb->m_MiniMd.FindNestedClassFor(RidFromToken(tkChild), &rid));
1775
1776 if (InvalidRid(rid))
1777 {
1778 // If not found, the *ptkParent has to be left unchanged! (callers depend on that)
1779 hr = S_OK;
1780 }
1781 else
1782 {
1783 NestedClassRec *pRecord;
1784 IfFailGo(m_pStgdb->m_MiniMd.GetNestedClassRecord(rid, &pRecord));
1785 *ptkParent = m_pStgdb->m_MiniMd.getEnclosingClassOfNestedClass(pRecord);
1786 }
1787 break;
1788 }
1789 case mdtMethodDef:
1790 IfFailGo(m_pStgdb->m_MiniMd.FindParentOfMethodHelper(RidFromToken(tkChild), ptkParent));
1791 RidToToken(*ptkParent, mdtTypeDef);
1792 break;
1793 case mdtMethodSpec:
1794 {
1795 MethodSpecRec *pRec;
1796 IfFailGo(m_pStgdb->m_MiniMd.GetMethodSpecRecord(RidFromToken(tkChild), &pRec));
1797 *ptkParent = m_pStgdb->m_MiniMd.getMethodOfMethodSpec(pRec);
1798 }
1799 break;
1800 case mdtFieldDef:
1801 IfFailGo(m_pStgdb->m_MiniMd.FindParentOfFieldHelper(RidFromToken(tkChild), ptkParent));
1802 RidToToken(*ptkParent, mdtTypeDef);
1803 break;
1804 case mdtParamDef:
1805 IfFailGo(m_pStgdb->m_MiniMd.FindParentOfParamHelper(RidFromToken(tkChild), ptkParent));
1806 RidToToken(*ptkParent, mdtMethodDef);
1807 break;
1808 case mdtMemberRef:
1809 {
1810 MemberRefRec *pRec;
1811 IfFailGo(m_pStgdb->m_MiniMd.GetMemberRefRecord(RidFromToken(tkChild), &pRec));
1812 *ptkParent = m_pStgdb->m_MiniMd.getClassOfMemberRef(pRec);
1813 break;
1814 }
1815 case mdtCustomAttribute:
1816 {
1817 CustomAttributeRec *pRec;
1818 IfFailGo(m_pStgdb->m_MiniMd.GetCustomAttributeRecord(RidFromToken(tkChild), &pRec));
1819 *ptkParent = m_pStgdb->m_MiniMd.getParentOfCustomAttribute(pRec);
1820 break;
1821 }
1822 case mdtEvent:
1823 IfFailGo(m_pStgdb->m_MiniMd.FindParentOfEventHelper(tkChild, ptkParent));
1824 break;
1825 case mdtProperty:
1826 IfFailGo(m_pStgdb->m_MiniMd.FindParentOfPropertyHelper(tkChild, ptkParent));
1827 break;
1828 default:
1829 _ASSERTE(!"NYI: for compressed format!");
1830 break;
1831 }
1832ErrExit:
1833 return hr;
1834} // MDInternalRW::GetParentToken
1835
1836//*****************************************************************************
1837// Get information about a CustomAttribute.
1838//*****************************************************************************
1839__checkReturn
1840HRESULT
1841MDInternalRW::GetCustomAttributeProps( // S_OK or error.
1842 mdCustomAttribute at, // The attribute.
1843 mdToken *pTkType) // Put attribute type here.
1844{
1845 HRESULT hr;
1846 // Getting the custom value prop with a token, no need to lock!
1847
1848 _ASSERTE(TypeFromToken(at) == mdtCustomAttribute);
1849
1850 // Do a linear search on compressed version as we do not want to
1851 // depend on ICR.
1852 //
1853 CustomAttributeRec *pCustomAttributeRec;
1854
1855 IfFailRet(m_pStgdb->m_MiniMd.GetCustomAttributeRecord(RidFromToken(at), &pCustomAttributeRec));
1856 *pTkType = m_pStgdb->m_MiniMd.getTypeOfCustomAttribute(pCustomAttributeRec);
1857 return S_OK;
1858} // MDInternalRW::GetCustomAttributeProps
1859
1860
1861//*****************************************************************************
1862// return custom value
1863//*****************************************************************************
1864__checkReturn
1865HRESULT
1866MDInternalRW::GetCustomAttributeAsBlob(
1867 mdCustomAttribute cv, // [IN] given custom attribute token
1868 void const **ppBlob, // [OUT] return the pointer to internal blob
1869 ULONG *pcbSize) // [OUT] return the size of the blob
1870{
1871 // Getting the custom value prop with a token, no need to lock!
1872 HRESULT hr;
1873 _ASSERTE(ppBlob && pcbSize && TypeFromToken(cv) == mdtCustomAttribute);
1874
1875 CustomAttributeRec *pCustomAttributeRec;
1876
1877 IfFailRet(m_pStgdb->m_MiniMd.GetCustomAttributeRecord(RidFromToken(cv), &pCustomAttributeRec));
1878
1879 IfFailRet(m_pStgdb->m_MiniMd.getValueOfCustomAttribute(pCustomAttributeRec, reinterpret_cast<const BYTE **>(ppBlob), pcbSize));
1880 return S_OK;
1881} // MDInternalRW::GetCustomAttributeAsBlob
1882
1883//*****************************************************************************
1884// Helper function to lookup and retrieve a CustomAttribute.
1885//*****************************************************************************
1886__checkReturn
1887HRESULT MDInternalRW::GetCustomAttributeByName( // S_OK or error.
1888 mdToken tkObj, // [IN] Object with Custom Attribute.
1889 LPCUTF8 szName, // [IN] Name of desired Custom Attribute.
1890 __deref_out_bcount(*pcbData) const void **ppData, // [OUT] Put pointer to data here.
1891 __out ULONG *pcbData) // [OUT] Put size of data here.
1892{
1893 HRESULT hr = S_OK;
1894 LOCKREADIFFAILRET();
1895 return m_pStgdb->m_MiniMd.CommonGetCustomAttributeByName(tkObj, szName, ppData, pcbData);
1896} // MDInternalRW::GetCustomAttributeByName
1897
1898//*****************************************************************************
1899// return the name of a custom attribute
1900//*****************************************************************************
1901__checkReturn
1902HRESULT MDInternalRW::GetNameOfCustomAttribute( // S_OK or error.
1903 mdCustomAttribute mdAttribute, // [IN] The Custom Attribute
1904 LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute.
1905 LPCUTF8 *pszName) // [OUT] Name of Custom Attribute.
1906{
1907 HRESULT hr = S_OK;
1908 LOCKREADIFFAILRET();
1909 hr = m_pStgdb->m_MiniMd.CommonGetNameOfCustomAttribute(RidFromToken(mdAttribute), pszNamespace, pszName);
1910 return (hr == S_FALSE) ? E_FAIL : hr;
1911} // MDInternalRW::GetNameOfCustomAttribute
1912
1913//*****************************************************************************
1914// return scope properties
1915//*****************************************************************************
1916__checkReturn
1917HRESULT MDInternalRW::GetScopeProps(
1918 LPCSTR *pszName, // [OUT] scope name
1919 GUID *pmvid) // [OUT] version id
1920{
1921 HRESULT hr = S_OK;
1922 LOCKREAD();
1923
1924 ModuleRec *pModuleRec;
1925
1926 // there is only one module record
1927 IfFailGo(m_pStgdb->m_MiniMd.GetModuleRecord(1, &pModuleRec));
1928
1929 if (pmvid != NULL)
1930 {
1931 IfFailGo(m_pStgdb->m_MiniMd.getMvidOfModule(pModuleRec, pmvid));
1932 }
1933
1934 if (pszName != NULL)
1935 {
1936 IfFailGo(m_pStgdb->m_MiniMd.getNameOfModule(pModuleRec, pszName));
1937 }
1938
1939ErrExit:
1940 return hr;
1941} // MDInternalRW::GetScopeProps
1942
1943//*****************************************************************************
1944// This function gets the "built for" version of a metadata scope.
1945// NOTE: if the scope has never been saved, it will not have a built-for
1946// version, and an empty string will be returned.
1947//*****************************************************************************
1948__checkReturn
1949HRESULT MDInternalRW::GetVersionString( // S_OK or error.
1950 LPCSTR *pVer) // [OUT] Put version string here.
1951{
1952 HRESULT hr = NOERROR;
1953
1954 if (m_pStgdb->m_pvMd != NULL)
1955 {
1956 // For convenience, get a pointer to the version string.
1957 // @todo: get from alternate locations when there is no STOREAGESIGNATURE.
1958 *pVer = reinterpret_cast<const char*>(reinterpret_cast<const STORAGESIGNATURE*>(m_pStgdb->m_pvMd)->pVersion);
1959 }
1960 else
1961 { // No string.
1962 *pVer = NULL;
1963 }
1964
1965 return hr;
1966} // MDInternalRW::GetVersionString
1967
1968//*****************************************************************************
1969// Find a given member in a TypeDef (typically a class).
1970//*****************************************************************************
1971__checkReturn
1972HRESULT MDInternalRW::FindMethodDef(// S_OK or error.
1973 mdTypeDef classdef, // The owning class of the member.
1974 LPCSTR szName, // Name of the member in utf8.
1975 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
1976 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
1977 mdMethodDef *pmethoddef) // Put MemberDef token here.
1978{
1979 HRESULT hr = S_OK;
1980 LOCKREAD();
1981
1982 _ASSERTE(szName && pmethoddef);
1983
1984 IfFailGo(ImportHelper::FindMethod(&(m_pStgdb->m_MiniMd),
1985 classdef,
1986 szName,
1987 pvSigBlob,
1988 cbSigBlob,
1989 pmethoddef));
1990
1991ErrExit:
1992 return hr;
1993}
1994
1995//*****************************************************************************
1996// Find a given member in a TypeDef (typically a class).
1997//*****************************************************************************
1998__checkReturn
1999HRESULT MDInternalRW::FindMethodDefUsingCompare(// S_OK or error.
2000 mdTypeDef classdef, // The owning class of the member.
2001 LPCSTR szName, // Name of the member in utf8.
2002 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
2003 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
2004 PSIGCOMPARE pSignatureCompare, // [IN] Routine to compare signatures
2005 void* pSignatureArgs, // [IN] Additional info to supply the compare function
2006 mdMethodDef *pmethoddef) // Put MemberDef token here.
2007{
2008 HRESULT hr = S_OK;
2009 LOCKREAD();
2010
2011 _ASSERTE(szName && pmethoddef);
2012
2013 IfFailGo(ImportHelper::FindMethod(&(m_pStgdb->m_MiniMd),
2014 classdef,
2015 szName,
2016 pvSigBlob,
2017 cbSigBlob,
2018 pmethoddef,
2019 0,
2020 pSignatureCompare,
2021 pSignatureArgs));
2022
2023ErrExit:
2024 return hr;
2025}
2026
2027//*****************************************************************************
2028// Find a given param of a Method.
2029//*****************************************************************************
2030__checkReturn
2031HRESULT MDInternalRW::FindParamOfMethod(// S_OK or error.
2032 mdMethodDef md, // [IN] The owning method of the param.
2033 ULONG iSeq, // [IN] The sequence # of the param.
2034 mdParamDef *pparamdef) // [OUT] Put ParamDef token here.
2035{
2036 ParamRec *pParamRec;
2037 RID ridStart, ridEnd;
2038 HRESULT hr = NOERROR;
2039 MethodRec *pMethodRec = NULL;
2040
2041 LOCKREAD();
2042
2043 _ASSERTE(TypeFromToken(md) == mdtMethodDef && pparamdef);
2044
2045 // get the methoddef record
2046 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
2047
2048 // figure out the start rid and end rid of the parameter list of this methoddef
2049 ridStart = m_pStgdb->m_MiniMd.getParamListOfMethod(pMethodRec);
2050 IfFailGo(m_pStgdb->m_MiniMd.getEndParamListOfMethod(RidFromToken(md), &ridEnd));
2051
2052 // loop through each param
2053 //
2054 for (; ridStart < ridEnd; ridStart++)
2055 {
2056 RID paramRid;
2057 IfFailGo(m_pStgdb->m_MiniMd.GetParamRid(ridStart, &paramRid));
2058 IfFailGo(m_pStgdb->m_MiniMd.GetParamRecord(paramRid, &pParamRec));
2059 if (iSeq == m_pStgdb->m_MiniMd.getSequenceOfParam( pParamRec) )
2060 {
2061 // parameter has the sequence number matches what we are looking for
2062 *pparamdef = TokenFromRid(paramRid, mdtParamDef );
2063 goto ErrExit;
2064 }
2065 }
2066 hr = CLDB_E_RECORD_NOTFOUND;
2067ErrExit:
2068
2069 return hr;
2070} // MDInternalRW::FindParamOfMethod
2071
2072
2073
2074//*****************************************************************************
2075// return a pointer which points to meta data's internal string
2076// return the the type name in utf8
2077//*****************************************************************************
2078__checkReturn
2079HRESULT
2080MDInternalRW::GetNameOfTypeDef( // return hresult
2081 mdTypeDef classdef, // given typedef
2082 LPCSTR* pszname, // pointer to an internal UTF8 string
2083 LPCSTR* psznamespace) // pointer to the namespace.
2084{
2085 // No need to lock this method.
2086 HRESULT hr;
2087
2088 if (pszname != NULL)
2089 {
2090 *pszname = NULL;
2091 }
2092 if (psznamespace != NULL)
2093 {
2094 *psznamespace = NULL;
2095 }
2096
2097 if (TypeFromToken(classdef) == mdtTypeDef)
2098 {
2099 TypeDefRec *pTypeDefRec;
2100 IfFailRet(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(classdef), &pTypeDefRec));
2101
2102 if (pszname != NULL)
2103 {
2104 IfFailRet(m_pStgdb->m_MiniMd.getNameOfTypeDef(pTypeDefRec, pszname));
2105 }
2106
2107 if (psznamespace != NULL)
2108 {
2109 IfFailRet(m_pStgdb->m_MiniMd.getNamespaceOfTypeDef(pTypeDefRec, psznamespace));
2110 }
2111 return S_OK;
2112 }
2113
2114 _ASSERTE(!"Invalid argument(s) of GetNameOfTypeDef");
2115 return CLDB_E_INTERNALERROR;
2116} // MDInternalRW::GetNameOfTypeDef
2117
2118//*****************************************************************************
2119// return pDual indicating if the given TypeDef is marked as a Dual interface
2120//*****************************************************************************
2121__checkReturn
2122HRESULT MDInternalRW::GetIsDualOfTypeDef(// return hresult
2123 mdTypeDef classdef, // given classdef
2124 ULONG *pDual) // [OUT] return dual flag here.
2125{
2126 ULONG iFace=0; // Iface type.
2127 HRESULT hr; // A result.
2128
2129 // no need to lock at this level
2130
2131 hr = GetIfaceTypeOfTypeDef(classdef, &iFace);
2132 if (hr == S_OK)
2133 *pDual = (iFace == ifDual);
2134 else
2135 *pDual = 1;
2136
2137 return hr;
2138} // MDInternalRW::GetIsDualOfTypeDef
2139
2140__checkReturn
2141HRESULT MDInternalRW::GetIfaceTypeOfTypeDef(
2142 mdTypeDef classdef, // [IN] given classdef.
2143 ULONG *pIface) // [OUT] 0=dual, 1=vtable, 2=dispinterface
2144{
2145 HRESULT hr; // A result.
2146 const BYTE *pVal; // The custom value.
2147 ULONG cbVal; // Size of the custom value.
2148 ULONG ItfType = DEFAULT_COM_INTERFACE_TYPE; // Set the interface type to the default.
2149
2150 // all of the public functions that it calls have proper locked
2151
2152 // If the value is not present, the class is assumed dual.
2153 hr = GetCustomAttributeByName(classdef, INTEROP_INTERFACETYPE_TYPE, (const void**)&pVal, &cbVal);
2154 if (hr == S_OK)
2155 {
2156 _ASSERTE("The ComInterfaceType custom attribute is invalid" && cbVal);
2157 _ASSERTE("ComInterfaceType custom attribute does not have the right format" && (*pVal == 0x01) && (*(pVal + 1) == 0x00));
2158 ItfType = *(pVal + 2);
2159 if (ItfType >= ifLast)
2160 ItfType = DEFAULT_COM_INTERFACE_TYPE;
2161 }
2162
2163 // Set the return value.
2164 *pIface = ItfType;
2165
2166 return hr;
2167} // MDInternalRW::GetIfaceTypeOfTypeDef
2168
2169//*****************************************************************************
2170// Given a methoddef, return a pointer to methoddef's name
2171//*****************************************************************************
2172__checkReturn
2173HRESULT
2174MDInternalRW::GetNameOfMethodDef(
2175 mdMethodDef md,
2176 LPCSTR *pszMethodName)
2177{
2178 // name of method will not change. So no need to lock
2179 HRESULT hr;
2180 MethodRec *pMethodRec;
2181 *pszMethodName = NULL;
2182 IfFailRet(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
2183 IfFailRet(m_pStgdb->m_MiniMd.getNameOfMethod(pMethodRec, pszMethodName));
2184 return S_OK;
2185} // MDInternalRW::GetNameOfMethodDef
2186
2187
2188//*****************************************************************************
2189// Given a methoddef, return a pointer to methoddef's signature and methoddef's name
2190//*****************************************************************************
2191__checkReturn
2192HRESULT
2193MDInternalRW::GetNameAndSigOfMethodDef(
2194 mdMethodDef methoddef, // [IN] given memberdef
2195 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature
2196 ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
2197 LPCSTR *pszMethodName)
2198{
2199 HRESULT hr;
2200 // we don't need lock here because name and signature will not change
2201
2202 // Output parameter should not be NULL
2203 _ASSERTE(ppvSigBlob && pcbSigBlob);
2204 _ASSERTE(TypeFromToken(methoddef) == mdtMethodDef);
2205
2206 MethodRec *pMethodRec;
2207 *pszMethodName = NULL;
2208 *ppvSigBlob = NULL;
2209 *ppvSigBlob = NULL;
2210 IfFailRet(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec));
2211 IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfMethod(pMethodRec, ppvSigBlob, pcbSigBlob));
2212
2213 return GetNameOfMethodDef(methoddef, pszMethodName);
2214} // MDInternalRW::GetNameAndSigOfMethodDef
2215
2216
2217//*****************************************************************************
2218// Given a FieldDef, return a pointer to FieldDef's name in UTF8
2219//*****************************************************************************
2220__checkReturn
2221HRESULT
2222MDInternalRW::GetNameOfFieldDef( // return hresult
2223 mdFieldDef fd, // given field
2224 LPCSTR *pszFieldName)
2225{
2226 // we don't need lock here because name of field will not change
2227 HRESULT hr;
2228
2229 FieldRec *pFieldRec;
2230 *pszFieldName = NULL;
2231 IfFailRet(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec));
2232 IfFailRet(m_pStgdb->m_MiniMd.getNameOfField(pFieldRec, pszFieldName));
2233 return S_OK;
2234} // MDInternalRW::GetNameOfFieldDef
2235
2236
2237//*****************************************************************************
2238// Given a classdef, return a pointer to classdef's name in UTF8
2239//*****************************************************************************
2240__checkReturn
2241HRESULT
2242MDInternalRW::GetNameOfTypeRef( // return TypeDef's name
2243 mdTypeRef classref, // [IN] given typeref
2244 LPCSTR *psznamespace, // [OUT] return typeref name
2245 LPCSTR *pszname) // [OUT] return typeref namespace
2246{
2247 _ASSERTE(TypeFromToken(classref) == mdtTypeRef);
2248 HRESULT hr;
2249
2250 *psznamespace = NULL;
2251 *pszname = NULL;
2252
2253 // we don't need lock here because name of a typeref will not change
2254
2255 TypeRefRec *pTypeRefRec;
2256 IfFailRet(m_pStgdb->m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec));
2257 IfFailRet(m_pStgdb->m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, psznamespace));
2258 IfFailRet(m_pStgdb->m_MiniMd.getNameOfTypeRef(pTypeRefRec, pszname));
2259 return S_OK;
2260} // MDInternalRW::GetNameOfTypeRef
2261
2262//*****************************************************************************
2263// return the resolutionscope of typeref
2264//*****************************************************************************
2265__checkReturn
2266HRESULT
2267MDInternalRW::GetResolutionScopeOfTypeRef(
2268 mdTypeRef classref, // given classref
2269 mdToken *ptkResolutionScope)
2270{
2271 HRESULT hr = S_OK;
2272 TypeRefRec *pTypeRefRec = NULL;
2273
2274 LOCKREAD();
2275
2276 _ASSERTE(TypeFromToken(classref) == mdtTypeRef && RidFromToken(classref));
2277
2278 IfFailGo(m_pStgdb->m_MiniMd.GetTypeRefRecord(RidFromToken(classref), &pTypeRefRec));
2279 _ASSERTE(hr == S_OK);
2280 *ptkResolutionScope = m_pStgdb->m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec);
2281 return S_OK;
2282
2283ErrExit:
2284 *ptkResolutionScope = mdTokenNil;
2285 return hr;
2286} // MDInternalRW::GetResolutionScopeOfTypeRef
2287
2288//*****************************************************************************
2289// Given a name, find the corresponding TypeRef.
2290//*****************************************************************************
2291__checkReturn
2292HRESULT MDInternalRW::FindTypeRefByName( // S_OK or error.
2293 LPCSTR szNamespace, // [IN] Namespace for the TypeRef.
2294 LPCSTR szName, // [IN] Name of the TypeRef.
2295 mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef.
2296 mdTypeRef *ptk) // [OUT] TypeRef token returned.
2297{
2298 HRESULT hr = NOERROR;
2299 ULONG cTypeRefRecs;
2300 TypeRefRec *pTypeRefRec;
2301 LPCUTF8 szNamespaceTmp;
2302 LPCUTF8 szNameTmp;
2303 mdToken tkRes;
2304
2305 LOCKREAD();
2306 _ASSERTE(ptk);
2307
2308 // initialize the output parameter
2309 *ptk = mdTypeRefNil;
2310
2311 // Treat no namespace as empty string.
2312 if (!szNamespace)
2313 szNamespace = "";
2314
2315 // It is a linear search here. Do we want to instantiate the name hash?
2316 cTypeRefRecs = m_pStgdb->m_MiniMd.getCountTypeRefs();
2317
2318 for (ULONG i = 1; i <= cTypeRefRecs; i++)
2319 {
2320 IfFailGo(m_pStgdb->m_MiniMd.GetTypeRefRecord(i, &pTypeRefRec));
2321
2322 tkRes = m_pStgdb->m_MiniMd.getResolutionScopeOfTypeRef(pTypeRefRec);
2323 if (IsNilToken(tkRes))
2324 {
2325 if (!IsNilToken(tkResolutionScope))
2326 continue;
2327 }
2328 else if (tkRes != tkResolutionScope)
2329 continue;
2330
2331 IfFailGo(m_pStgdb->m_MiniMd.getNamespaceOfTypeRef(pTypeRefRec, &szNamespaceTmp));
2332 if (strcmp(szNamespace, szNamespaceTmp))
2333 continue;
2334
2335 IfFailGo(m_pStgdb->m_MiniMd.getNameOfTypeRef(pTypeRefRec, &szNameTmp));
2336 if (!strcmp(szNameTmp, szName))
2337 {
2338 *ptk = TokenFromRid(i, mdtTypeRef);
2339 goto ErrExit;
2340 }
2341 }
2342
2343 // cannot find the typedef
2344 hr = CLDB_E_RECORD_NOTFOUND;
2345ErrExit:
2346 return hr;
2347} // MDInternalRW::FindTypeRefByName
2348
2349//*****************************************************************************
2350// return flags for a given class
2351//*****************************************************************************
2352__checkReturn
2353HRESULT MDInternalRW::GetTypeDefProps(
2354 mdTypeDef td, // given classdef
2355 DWORD *pdwAttr, // return flags on class
2356 mdToken *ptkExtends) // [OUT] Put base class TypeDef/TypeRef here.
2357{
2358 HRESULT hr = S_OK;
2359 TypeDefRec *pTypeDefRec = NULL;
2360 LOCKREAD();
2361
2362 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec));
2363
2364 if (ptkExtends)
2365 {
2366 *ptkExtends = m_pStgdb->m_MiniMd.getExtendsOfTypeDef(pTypeDefRec);
2367 }
2368 if (pdwAttr)
2369 {
2370 *pdwAttr = m_pStgdb->m_MiniMd.getFlagsOfTypeDef(pTypeDefRec);
2371 }
2372
2373ErrExit:
2374
2375 return hr;
2376} // MDInternalRW::GetTypeDefProps
2377
2378
2379//*****************************************************************************
2380// return guid pointer to MetaData internal guid pool given a given class
2381//*****************************************************************************
2382__checkReturn
2383HRESULT MDInternalRW::GetItemGuid( // return hresult
2384 mdToken tkObj, // given item.
2385 CLSID *pGuid) // [OUT] put guid here.
2386{
2387
2388 HRESULT hr; // A result.
2389 const BYTE *pBlob = NULL; // Blob with dispid.
2390 ULONG cbBlob; // Length of blob.
2391 WCHAR wzBlob[40]; // Wide char format of guid.
2392 int ix; // Loop control.
2393
2394 // Get the GUID, if any.
2395 hr = GetCustomAttributeByName(tkObj, INTEROP_GUID_TYPE, (const void**)&pBlob, &cbBlob);
2396 if (SUCCEEDED(hr) && hr != S_FALSE)
2397 {
2398 // Should be in format. Total length == 41
2399 // <0x0001><0x24>01234567-0123-0123-0123-001122334455<0x0000>
2400 if ((cbBlob != 41) || (GET_UNALIGNED_VAL16(pBlob) != 1))
2401 IfFailGo(E_INVALIDARG);
2402 for (ix=1; ix<=36; ++ix)
2403 wzBlob[ix] = pBlob[ix+2];
2404 wzBlob[0] = '{';
2405 wzBlob[37] = '}';
2406 wzBlob[38] = 0;
2407 hr = IIDFromString(wzBlob, pGuid);
2408 }
2409 else
2410 *pGuid = GUID_NULL;
2411
2412ErrExit:
2413 return hr;
2414} // MDInternalRW::GetItemGuid
2415
2416//*****************************************************************************
2417// // get enclosing class of NestedClass
2418//*****************************************************************************
2419__checkReturn
2420HRESULT
2421MDInternalRW::GetNestedClassProps(
2422 mdTypeDef tkNestedClass, // [IN] NestedClass token.
2423 mdTypeDef *ptkEnclosingClass) // [OUT] EnclosingClass token.
2424{
2425 HRESULT hr = NOERROR;
2426 RID rid;
2427
2428 BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW);
2429
2430 LOCKREAD();
2431
2432 if (!m_pStgdb->m_MiniMd.IsSorted(TBL_NestedClass) && !m_pStgdb->m_MiniMd.IsTableVirtualSorted(TBL_NestedClass))
2433 {
2434 // NestedClass table is not sorted.
2435 CONVERT_READ_TO_WRITE_LOCK();
2436 }
2437
2438 // This is a binary search thus we need to grap a read lock. Or this table
2439 // might be sorted underneath our feet.
2440
2441 _ASSERTE(TypeFromToken(tkNestedClass) == mdtTypeDef && ptkEnclosingClass);
2442
2443 IfFailGo(m_pStgdb->m_MiniMd.FindNestedClassFor(RidFromToken(tkNestedClass), &rid));
2444
2445 if (InvalidRid(rid))
2446 {
2447 hr = CLDB_E_RECORD_NOTFOUND;
2448 }
2449 else
2450 {
2451 NestedClassRec *pRecord;
2452 IfFailGo(m_pStgdb->m_MiniMd.GetNestedClassRecord(rid, &pRecord));
2453 *ptkEnclosingClass = m_pStgdb->m_MiniMd.getEnclosingClassOfNestedClass(pRecord);
2454 }
2455
2456ErrExit:
2457 END_SO_INTOLERANT_CODE;
2458 return hr;
2459} // MDInternalRW::GetNestedClassProps
2460
2461//*******************************************************************************
2462// Get count of Nested classes given the enclosing class.
2463//*******************************************************************************
2464__checkReturn
2465HRESULT
2466MDInternalRW::GetCountNestedClasses( // return count of Nested classes.
2467 mdTypeDef tkEnclosingClass, // [IN]Enclosing class.
2468 ULONG *pcNestedClassesCount)
2469{
2470 HRESULT hr;
2471 ULONG ulCount;
2472 ULONG ulRetCount = 0;
2473 NestedClassRec *pRecord;
2474
2475 _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef && !IsNilToken(tkEnclosingClass));
2476
2477 *pcNestedClassesCount = 0;
2478
2479 ulCount = m_pStgdb->m_MiniMd.getCountNestedClasss();
2480
2481 for (ULONG i = 1; i <= ulCount; i++)
2482 {
2483 IfFailRet(m_pStgdb->m_MiniMd.GetNestedClassRecord(i, &pRecord));
2484 if (tkEnclosingClass == m_pStgdb->m_MiniMd.getEnclosingClassOfNestedClass(pRecord))
2485 ulRetCount++;
2486 }
2487 *pcNestedClassesCount = ulRetCount;
2488 return S_OK;
2489} // MDInternalRW::GetCountNestedClasses
2490
2491//*******************************************************************************
2492// Return array of Nested classes given the enclosing class.
2493//*******************************************************************************
2494__checkReturn
2495HRESULT
2496MDInternalRW::GetNestedClasses( // Return actual count.
2497 mdTypeDef tkEnclosingClass, // [IN] Enclosing class.
2498 mdTypeDef *rNestedClasses, // [OUT] Array of nested class tokens.
2499 ULONG ulNestedClasses, // [IN] Size of array.
2500 ULONG *pcNestedClasses)
2501{
2502 HRESULT hr;
2503 ULONG ulCount;
2504 ULONG ulRetCount = 0;
2505 NestedClassRec *pRecord;
2506
2507 _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef &&
2508 !IsNilToken(tkEnclosingClass));
2509
2510 *pcNestedClasses = 0;
2511
2512 ulCount = m_pStgdb->m_MiniMd.getCountNestedClasss();
2513
2514 for (ULONG i = 1; i <= ulCount; i++)
2515 {
2516 IfFailRet(m_pStgdb->m_MiniMd.GetNestedClassRecord(i, &pRecord));
2517 if (tkEnclosingClass == m_pStgdb->m_MiniMd.getEnclosingClassOfNestedClass(pRecord))
2518 {
2519 if (ovadd_le(ulRetCount, 1, ulNestedClasses)) // ulRetCount is 0 based.
2520 rNestedClasses[ulRetCount] = m_pStgdb->m_MiniMd.getNestedClassOfNestedClass(pRecord);
2521 ulRetCount++;
2522 }
2523 }
2524 *pcNestedClasses = ulRetCount;
2525 return S_OK;
2526} // MDInternalRW::GetNestedClasses
2527
2528//*******************************************************************************
2529// return the ModuleRef properties
2530//*******************************************************************************
2531__checkReturn
2532HRESULT MDInternalRW::GetModuleRefProps( // return hresult
2533 mdModuleRef mur, // [IN] moduleref token
2534 LPCSTR *pszName) // [OUT] buffer to fill with the moduleref name
2535{
2536 _ASSERTE(TypeFromToken(mur) == mdtModuleRef);
2537 _ASSERTE(pszName);
2538
2539 HRESULT hr = S_OK;
2540 ModuleRefRec *pModuleRefRec = NULL;
2541 LOCKREAD();
2542
2543 IfFailGo(m_pStgdb->m_MiniMd.GetModuleRefRecord(RidFromToken(mur), &pModuleRefRec));
2544 IfFailGo(m_pStgdb->m_MiniMd.getNameOfModuleRef(pModuleRefRec, pszName));
2545
2546ErrExit:
2547
2548 return hr;
2549} // MDInternalRW::GetModuleRefProps
2550
2551
2552
2553//*****************************************************************************
2554// Given a scope and a methoddef, return a pointer to methoddef's signature
2555//*****************************************************************************
2556__checkReturn
2557HRESULT
2558MDInternalRW::GetSigOfMethodDef(
2559 mdMethodDef methoddef, // given a methoddef
2560 ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
2561 PCCOR_SIGNATURE *ppSig)
2562{
2563 // Output parameter should not be NULL
2564 _ASSERTE(pcbSigBlob);
2565 _ASSERTE(TypeFromToken(methoddef) == mdtMethodDef);
2566
2567 HRESULT hr;
2568 // We don't change MethodDef signature. No need to lock.
2569
2570 MethodRec *pMethodRec;
2571 *ppSig = NULL;
2572 *pcbSigBlob = 0;
2573 IfFailRet(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(methoddef), &pMethodRec));
2574 IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfMethod(pMethodRec, ppSig, pcbSigBlob));
2575 return S_OK;
2576} // MDInternalRW::GetSigOfMethodDef
2577
2578
2579//*****************************************************************************
2580// Given a scope and a fielddef, return a pointer to fielddef's signature
2581//*****************************************************************************
2582__checkReturn
2583HRESULT
2584MDInternalRW::GetSigOfFieldDef(
2585 mdFieldDef fielddef, // given a methoddef
2586 ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
2587 PCCOR_SIGNATURE *ppSig)
2588{
2589 _ASSERTE(pcbSigBlob);
2590 _ASSERTE(TypeFromToken(fielddef) == mdtFieldDef);
2591
2592 HRESULT hr;
2593 // We don't change Field's signature. No need to lock.
2594
2595 FieldRec *pFieldRec;
2596 *ppSig = NULL;
2597 *pcbSigBlob = 0;
2598 IfFailRet(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(fielddef), &pFieldRec));
2599 IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfField(pFieldRec, ppSig, pcbSigBlob));
2600 return S_OK;
2601} // MDInternalRW::GetSigOfFieldDef
2602
2603
2604//*****************************************************************************
2605// Get signature for the token (FieldDef, MethodDef, Signature, or TypeSpec).
2606//*****************************************************************************
2607__checkReturn
2608HRESULT
2609MDInternalRW::GetSigFromToken(
2610 mdToken tk,
2611 ULONG * pcbSig,
2612 PCCOR_SIGNATURE * ppSig)
2613{
2614 HRESULT hr;
2615 // We don't change token's signature. Thus no need to lock.
2616
2617 *ppSig = NULL;
2618 *pcbSig = 0;
2619 switch (TypeFromToken(tk))
2620 {
2621 case mdtSignature:
2622 {
2623 StandAloneSigRec *pRec;
2624 IfFailGo(m_pStgdb->m_MiniMd.GetStandAloneSigRecord(RidFromToken(tk), &pRec));
2625 IfFailGo(m_pStgdb->m_MiniMd.getSignatureOfStandAloneSig(pRec, ppSig, pcbSig));
2626 return S_OK;
2627 }
2628 case mdtTypeSpec:
2629 {
2630 TypeSpecRec *pRec;
2631 IfFailGo(m_pStgdb->m_MiniMd.GetTypeSpecRecord(RidFromToken(tk), &pRec));
2632 IfFailGo(m_pStgdb->m_MiniMd.getSignatureOfTypeSpec(pRec, ppSig, pcbSig));
2633 return S_OK;
2634 }
2635 case mdtMethodDef:
2636 {
2637 IfFailGo(GetSigOfMethodDef(tk, pcbSig, ppSig));
2638 return S_OK;
2639 }
2640 case mdtFieldDef:
2641 {
2642 IfFailGo(GetSigOfFieldDef(tk, pcbSig, ppSig));
2643 return S_OK;
2644 }
2645 }
2646
2647 // not a known token type.
2648#ifdef _DEBUG
2649 if(REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::INTERNAL_AssertOnBadImageFormat, 1))
2650 _ASSERTE(!"Unexpected token type");
2651#endif
2652 *pcbSig = 0;
2653 hr = META_E_INVALID_TOKEN_TYPE;
2654
2655ErrExit:
2656 return hr;
2657} // MDInternalRW::GetSigFromToken
2658
2659
2660//*****************************************************************************
2661// Given methoddef, return the flags
2662//*****************************************************************************
2663__checkReturn
2664HRESULT
2665MDInternalRW::GetMethodDefProps(
2666 mdMethodDef md,
2667 DWORD *pdwFlags) // return mdPublic, mdAbstract, etc
2668{
2669 HRESULT hr = S_OK;
2670 MethodRec *pMethodRec = NULL;
2671
2672 LOCKREAD();
2673
2674 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
2675 _ASSERTE(hr == S_OK);
2676 *pdwFlags = m_pStgdb->m_MiniMd.getFlagsOfMethod(pMethodRec);
2677 return S_OK;
2678
2679ErrExit:
2680 *pdwFlags = (DWORD)-1;
2681 return hr;
2682} // MDInternalRW::GetMethodDefProps
2683
2684//*****************************************************************************
2685// Given a scope and a methoddef, return RVA and impl flags
2686//*****************************************************************************
2687__checkReturn
2688HRESULT MDInternalRW::GetMethodImplProps(
2689 mdToken tk, // [IN] MethodDef
2690 ULONG *pulCodeRVA, // [OUT] CodeRVA
2691 DWORD *pdwImplFlags) // [OUT] Impl. Flags
2692{
2693 _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
2694 HRESULT hr = S_OK;
2695 MethodRec *pMethodRec = NULL;
2696
2697 LOCKREAD();
2698
2699 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(tk), &pMethodRec));
2700
2701 if (pulCodeRVA)
2702 {
2703 *pulCodeRVA = m_pStgdb->m_MiniMd.getRVAOfMethod(pMethodRec);
2704 }
2705
2706 if (pdwImplFlags)
2707 {
2708 *pdwImplFlags = m_pStgdb->m_MiniMd.getImplFlagsOfMethod(pMethodRec);
2709 }
2710
2711ErrExit:
2712
2713 return hr;
2714} // MDInternalRW::GetMethodImplProps
2715
2716
2717//*****************************************************************************
2718// return the field RVA
2719//*****************************************************************************
2720__checkReturn
2721HRESULT MDInternalRW::GetFieldRVA(
2722 mdToken fd, // [IN] FieldDef
2723 ULONG *pulCodeRVA) // [OUT] CodeRVA
2724{
2725 _ASSERTE(TypeFromToken(fd) == mdtFieldDef);
2726 _ASSERTE(pulCodeRVA);
2727 ULONG iRecord;
2728 HRESULT hr = NOERROR;
2729
2730 LOCKREAD();
2731
2732 IfFailGo(m_pStgdb->m_MiniMd.FindFieldRVAHelper(fd, &iRecord));
2733 if (InvalidRid(iRecord))
2734 {
2735 if (pulCodeRVA)
2736 *pulCodeRVA = 0;
2737 hr = CLDB_E_RECORD_NOTFOUND;
2738 }
2739 else
2740 {
2741 FieldRVARec *pFieldRVARec;
2742 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRVARecord(iRecord, &pFieldRVARec));
2743
2744 *pulCodeRVA = m_pStgdb->m_MiniMd.getRVAOfFieldRVA(pFieldRVARec);
2745 }
2746
2747ErrExit:
2748 return hr;
2749} // MDInternalRW::GetFieldRVA
2750
2751
2752//*****************************************************************************
2753// Given a fielddef, return the flags. Such as fdPublic, fdStatic, etc
2754//*****************************************************************************
2755__checkReturn
2756HRESULT
2757MDInternalRW::GetFieldDefProps(
2758 mdFieldDef fd, // given memberdef
2759 DWORD *pdwFlags) // [OUT] return fdPublic, fdPrive, etc flags
2760{
2761 _ASSERTE(TypeFromToken(fd) == mdtFieldDef);
2762 HRESULT hr = S_OK;
2763 FieldRec *pFieldRec = NULL;
2764
2765 LOCKREAD();
2766
2767 IfFailRet(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec));
2768 _ASSERTE(hr == S_OK);
2769 *pdwFlags = m_pStgdb->m_MiniMd.getFlagsOfField(pFieldRec);
2770 return S_OK;
2771
2772ErrExit:
2773 *pdwFlags = (DWORD)-1;
2774 return hr;
2775} // MDInternalRW::GetFieldDefProps
2776
2777//*****************************************************************************
2778// return default value of a token(could be paramdef, fielddef, or property)
2779//*****************************************************************************
2780__checkReturn
2781HRESULT MDInternalRW::GetDefaultValue( // return hresult
2782 mdToken tk, // [IN] given FieldDef, ParamDef, or Property
2783 MDDefaultValue *pMDDefaultValue) // [OUT] default value
2784{
2785 _ASSERTE(pMDDefaultValue);
2786
2787 HRESULT hr;
2788 BYTE bType;
2789 const VOID *pValue;
2790 ULONG cbValue;
2791 RID rid;
2792 ConstantRec *pConstantRec;
2793
2794 LOCKREAD();
2795
2796 IfFailGo(m_pStgdb->m_MiniMd.FindConstantHelper(tk, &rid));
2797 if (InvalidRid(rid))
2798 {
2799 pMDDefaultValue->m_bType = ELEMENT_TYPE_VOID;
2800 return S_OK;
2801 }
2802 IfFailGo(m_pStgdb->m_MiniMd.GetConstantRecord(rid, &pConstantRec));
2803
2804 // get the type of constant value
2805 bType = m_pStgdb->m_MiniMd.getTypeOfConstant(pConstantRec);
2806
2807 // get the value blob
2808 IfFailGo(m_pStgdb->m_MiniMd.getValueOfConstant(pConstantRec, reinterpret_cast<const BYTE **>(&pValue), &cbValue));
2809
2810 // convert it to our internal default value representation
2811 hr = _FillMDDefaultValue(bType, pValue, cbValue, pMDDefaultValue);
2812
2813ErrExit:
2814
2815 return hr;
2816} // MDInternalRW::GetDefaultValue
2817
2818
2819//*****************************************************************************
2820// Given a scope and a methoddef/fielddef, return the dispid
2821//*****************************************************************************
2822__checkReturn
2823HRESULT MDInternalRW::GetDispIdOfMemberDef( // return hresult
2824 mdToken tk, // given methoddef or fielddef
2825 ULONG *pDispid) // Put the dispid here.
2826{
2827#ifdef FEATURE_COMINTEROP
2828 HRESULT hr; // A result.
2829 const BYTE *pBlob; // Blob with dispid.
2830 ULONG cbBlob; // Length of blob.
2831
2832 // No need to lock this function. All of the function that it is calling is already locked!
2833
2834 // Get the DISPID, if any.
2835 _ASSERTE(pDispid);
2836
2837 *pDispid = DISPID_UNKNOWN;
2838 hr = GetCustomAttributeByName(tk, INTEROP_DISPID_TYPE, (const void**)&pBlob, &cbBlob);
2839 if (hr != S_FALSE)
2840 {
2841 // Check that this might be a dispid.
2842 if (cbBlob >= (sizeof(*pDispid)+2))
2843 *pDispid = GET_UNALIGNED_VAL32(pBlob+2);
2844 else
2845 IfFailGo(E_INVALIDARG);
2846 }
2847
2848ErrExit:
2849 return hr;
2850#else // FEATURE_COMINTEROP
2851 _ASSERTE(false);
2852 return E_NOTIMPL;
2853#endif // FEATURE_COMINTEROP
2854} // MDInternalRW::GetDispIdOfMemberDef
2855
2856
2857//*****************************************************************************
2858// Given interfaceimpl, return the TypeRef/TypeDef and flags
2859//*****************************************************************************
2860__checkReturn
2861HRESULT
2862MDInternalRW::GetTypeOfInterfaceImpl( // return hresult
2863 mdInterfaceImpl iiImpl, // given a interfaceimpl
2864 mdToken *ptkType)
2865{
2866 HRESULT hr;
2867 // no need to lock this function.
2868
2869 _ASSERTE(TypeFromToken(iiImpl) == mdtInterfaceImpl);
2870
2871 *ptkType = mdTypeDefNil;
2872
2873 InterfaceImplRec *pIIRec;
2874 IfFailRet(m_pStgdb->m_MiniMd.GetInterfaceImplRecord(RidFromToken(iiImpl), &pIIRec));
2875 *ptkType = m_pStgdb->m_MiniMd.getInterfaceOfInterfaceImpl(pIIRec);
2876 return S_OK;
2877} // MDInternalRW::GetTypeOfInterfaceImpl
2878
2879//*****************************************************************************
2880// This routine gets the properties for the given MethodSpec token.
2881//*****************************************************************************
2882__checkReturn
2883HRESULT MDInternalRW::GetMethodSpecProps( // S_OK or error.
2884 mdMethodSpec mi, // [IN] The method instantiation
2885 mdToken *tkParent, // [OUT] MethodDef or MemberRef
2886 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
2887 ULONG *pcbSigBlob) // [OUT] actual size of signature blob
2888{
2889 HRESULT hr = NOERROR;
2890 MethodSpecRec *pMethodSpecRec;
2891
2892 _ASSERTE(TypeFromToken(mi) == mdtMethodSpec);
2893
2894 IfFailGo(m_pStgdb->m_MiniMd.GetMethodSpecRecord(RidFromToken(mi), &pMethodSpecRec));
2895
2896 if (tkParent)
2897 *tkParent = m_pStgdb->m_MiniMd.getMethodOfMethodSpec(pMethodSpecRec);
2898
2899 if (ppvSigBlob || pcbSigBlob)
2900 {
2901 // caller wants signature information
2902 PCCOR_SIGNATURE pvSigTmp;
2903 ULONG cbSig;
2904 IfFailGo(m_pStgdb->m_MiniMd.getInstantiationOfMethodSpec(pMethodSpecRec, &pvSigTmp, &cbSig));
2905 if ( ppvSigBlob )
2906 *ppvSigBlob = pvSigTmp;
2907 if ( pcbSigBlob)
2908 *pcbSigBlob = cbSig;
2909 }
2910
2911ErrExit:
2912 return hr;
2913} // MDInternalRW::GetMethodSpecProps
2914
2915//*****************************************************************************
2916// Given a classname, return the typedef
2917//*****************************************************************************
2918__checkReturn
2919HRESULT MDInternalRW::FindTypeDef( // return hresult
2920 LPCSTR szNamespace, // [IN] Namespace for the TypeDef.
2921 LPCSTR szName, // [IN] Name of the TypeDef.
2922 mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef of enclosing class.
2923 mdTypeDef *ptypedef) // [OUT] return typedef
2924{
2925 HRESULT hr = S_OK;
2926 LOCKREADIFFAILRET();
2927
2928 _ASSERTE(ptypedef);
2929
2930 // initialize the output parameter
2931 *ptypedef = mdTypeDefNil;
2932
2933 return ImportHelper::FindTypeDefByName(&(m_pStgdb->m_MiniMd),
2934 szNamespace,
2935 szName,
2936 tkEnclosingClass,
2937 ptypedef);
2938} // MDInternalRW::FindTypeDef
2939
2940//*****************************************************************************
2941// Given a memberref, return a pointer to memberref's name and signature
2942//*****************************************************************************
2943__checkReturn
2944HRESULT
2945MDInternalRW::GetNameAndSigOfMemberRef( // meberref's name
2946 mdMemberRef memberref, // given a memberref
2947 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of COM+ signature
2948 ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob
2949 LPCSTR *pszMemberRefName)
2950{
2951 HRESULT hr;
2952
2953 // MemberRef's name and sig won't change. Don't need to lock this.
2954
2955 _ASSERTE(TypeFromToken(memberref) == mdtMemberRef);
2956
2957 MemberRefRec *pMemberRefRec;
2958 *pszMemberRefName = NULL;
2959 if (ppvSigBlob != NULL)
2960 {
2961 _ASSERTE(pcbSigBlob != NULL);
2962 *ppvSigBlob = NULL;
2963 *pcbSigBlob = 0;
2964 }
2965 IfFailRet(m_pStgdb->m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec));
2966 if (ppvSigBlob != NULL)
2967 {
2968 IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfMemberRef(pMemberRefRec, ppvSigBlob, pcbSigBlob));
2969 }
2970 IfFailRet(m_pStgdb->m_MiniMd.getNameOfMemberRef(pMemberRefRec, pszMemberRefName));
2971 return S_OK;
2972} // MDInternalRW::GetNameAndSigOfMemberRef
2973
2974
2975
2976//*****************************************************************************
2977// Given a memberref, return parent token. It can be a TypeRef, ModuleRef, or a MethodDef
2978//*****************************************************************************
2979__checkReturn
2980HRESULT
2981MDInternalRW::GetParentOfMemberRef( // return parent token
2982 mdMemberRef memberref, // given a typedef
2983 mdToken *ptkParent) // return the parent token
2984{
2985 HRESULT hr = S_OK;
2986 MemberRefRec *pMemberRefRec = NULL;
2987
2988 LOCKREAD();
2989
2990 // parent for MemberRef can change. See SetParent.
2991
2992 _ASSERTE(TypeFromToken(memberref) == mdtMemberRef);
2993
2994 IfFailRet(m_pStgdb->m_MiniMd.GetMemberRefRecord(RidFromToken(memberref), &pMemberRefRec));
2995 _ASSERTE(hr == S_OK);
2996 *ptkParent = m_pStgdb->m_MiniMd.getClassOfMemberRef(pMemberRefRec);
2997 return S_OK;
2998
2999ErrExit:
3000 *ptkParent = mdTokenNil;
3001 return hr;
3002} // MDInternalRW::GetParentOfMemberRef
3003
3004//*****************************************************************************
3005// return properties of a paramdef
3006//*****************************************************************************/
3007__checkReturn
3008HRESULT
3009MDInternalRW::GetParamDefProps (
3010 mdParamDef paramdef, // given a paramdef
3011 USHORT *pusSequence, // [OUT] slot number for this parameter
3012 DWORD *pdwAttr, // [OUT] flags
3013 LPCSTR *pszName) // [OUT] return the name of the parameter
3014{
3015 HRESULT hr = S_OK;
3016 ParamRec *pParamRec = NULL;
3017
3018 LOCKREAD();
3019
3020 // parent for MemberRef can change. See SetParamProps.
3021
3022 _ASSERTE(TypeFromToken(paramdef) == mdtParamDef);
3023 IfFailGo(m_pStgdb->m_MiniMd.GetParamRecord(RidFromToken(paramdef), &pParamRec));
3024 _ASSERTE(hr == S_OK);
3025 if (pdwAttr != NULL)
3026 {
3027 *pdwAttr = m_pStgdb->m_MiniMd.getFlagsOfParam(pParamRec);
3028 }
3029 if (pusSequence != NULL)
3030 {
3031 *pusSequence = m_pStgdb->m_MiniMd.getSequenceOfParam(pParamRec);
3032 }
3033 IfFailGo(m_pStgdb->m_MiniMd.getNameOfParam(pParamRec, pszName));
3034 _ASSERTE(hr == S_OK);
3035 return S_OK;
3036
3037ErrExit:
3038 *pszName = NULL;
3039 return S_OK;
3040} // MDInternalRW::GetParamDefProps
3041
3042//*****************************************************************************
3043// Get property info for the method.
3044//*****************************************************************************
3045__checkReturn
3046HRESULT MDInternalRW::GetPropertyInfoForMethodDef( // Result.
3047 mdMethodDef md, // [IN] memberdef
3048 mdProperty *ppd, // [OUT] put property token here
3049 LPCSTR *pName, // [OUT] put pointer to name here
3050 ULONG *pSemantic) // [OUT] put semantic here
3051{
3052 MethodSemanticsRec *pSemantics;
3053 RID ridCur;
3054 RID ridMax;
3055 USHORT usSemantics;
3056 HRESULT hr = S_OK;
3057 LOCKREAD();
3058
3059 ridMax = m_pStgdb->m_MiniMd.getCountMethodSemantics();
3060 for (ridCur = 1; ridCur <= ridMax; ridCur++)
3061 {
3062 IfFailGo(m_pStgdb->m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
3063 if (md == m_pStgdb->m_MiniMd.getMethodOfMethodSemantics(pSemantics))
3064 {
3065 // match the method
3066 usSemantics = m_pStgdb->m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
3067 if (usSemantics == msGetter || usSemantics == msSetter)
3068 {
3069 // Make sure that it is not an invalid entry
3070 if (m_pStgdb->m_MiniMd.getAssociationOfMethodSemantics(pSemantics) != mdPropertyNil)
3071 {
3072 // found a match. Fill out the output parameters
3073 PropertyRec *pProperty;
3074 mdProperty prop;
3075 prop = m_pStgdb->m_MiniMd.getAssociationOfMethodSemantics(pSemantics);
3076
3077 if (ppd)
3078 *ppd = prop;
3079 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRecord(RidFromToken(prop), &pProperty));
3080
3081 if (pName)
3082 {
3083 IfFailGo(m_pStgdb->m_MiniMd.getNameOfProperty(pProperty, pName));
3084 }
3085
3086 if (pSemantic)
3087 *pSemantic = usSemantics;
3088 goto ErrExit;
3089 }
3090 }
3091 }
3092 }
3093
3094 hr = S_FALSE;
3095ErrExit:
3096 return hr;
3097} // MDInternalRW::GetPropertyInfoForMethodDef
3098
3099//*****************************************************************************
3100// return the pack size of a class
3101//*****************************************************************************
3102__checkReturn
3103HRESULT MDInternalRW::GetClassPackSize(
3104 mdTypeDef td, // [IN] give typedef
3105 DWORD *pdwPackSize) // [OUT]
3106{
3107 HRESULT hr = NOERROR;
3108 RID ridClassLayout = 0;
3109
3110 LOCKREAD();
3111
3112 _ASSERTE(TypeFromToken(td) == mdtTypeDef && pdwPackSize);
3113
3114 ClassLayoutRec *pRec;
3115 IfFailGo(m_pStgdb->m_MiniMd.FindClassLayoutHelper(td, &ridClassLayout));
3116
3117 if (InvalidRid(ridClassLayout))
3118 {
3119 hr = CLDB_E_RECORD_NOTFOUND;
3120 goto ErrExit;
3121 }
3122
3123 IfFailGo(m_pStgdb->m_MiniMd.GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec));
3124 *pdwPackSize = m_pStgdb->m_MiniMd.getPackingSizeOfClassLayout(pRec);
3125ErrExit:
3126 return hr;
3127} // MDInternalRW::GetClassPackSize
3128
3129
3130//*****************************************************************************
3131// return the total size of a value class
3132//*****************************************************************************
3133__checkReturn
3134HRESULT MDInternalRW::GetClassTotalSize( // return error if a class does not have total size info
3135 mdTypeDef td, // [IN] give typedef
3136 ULONG *pulClassSize) // [OUT] return the total size of the class
3137{
3138 CONTRACT_VIOLATION(ThrowsViolation);
3139
3140 _ASSERTE(TypeFromToken(td) == mdtTypeDef && pulClassSize);
3141
3142 ClassLayoutRec *pRec;
3143 HRESULT hr = NOERROR;
3144 RID ridClassLayout;
3145
3146 LOCKREAD();
3147
3148 IfFailGo(m_pStgdb->m_MiniMd.FindClassLayoutHelper(td, &ridClassLayout));
3149 if (InvalidRid(ridClassLayout))
3150 {
3151 hr = CLDB_E_RECORD_NOTFOUND;
3152 goto ErrExit;
3153 }
3154
3155 IfFailGo(m_pStgdb->m_MiniMd.GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec));
3156 *pulClassSize = m_pStgdb->m_MiniMd.getClassSizeOfClassLayout(pRec);
3157ErrExit:
3158 return hr;
3159} // MDInternalRW::GetClassTotalSize
3160
3161
3162//*****************************************************************************
3163// init the layout enumerator of a class
3164//*****************************************************************************
3165__checkReturn
3166HRESULT MDInternalRW::GetClassLayoutInit(
3167 mdTypeDef td, // [IN] give typedef
3168 MD_CLASS_LAYOUT *pmdLayout) // [OUT] set up the status of query here
3169{
3170 HRESULT hr = NOERROR;
3171 LOCKREAD();
3172 _ASSERTE(TypeFromToken(td) == mdtTypeDef);
3173
3174 // <TODO>Do we need to lock this function? Can clints add more Fields on a TypeDef?</TODO>
3175
3176 // initialize the output parameter
3177 _ASSERTE(pmdLayout);
3178 memset(pmdLayout, 0, sizeof(MD_CLASS_LAYOUT));
3179
3180 TypeDefRec *pTypeDefRec;
3181
3182 // record for this typedef in TypeDef Table
3183 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec));
3184
3185 // find the starting and end field for this typedef
3186 pmdLayout->m_ridFieldCur = m_pStgdb->m_MiniMd.getFieldListOfTypeDef(pTypeDefRec);
3187 IfFailGo(m_pStgdb->m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(td), &(pmdLayout->m_ridFieldEnd)));
3188
3189ErrExit:
3190
3191 return hr;
3192} // MDInternalRW::GetClassLayoutInit
3193
3194//*****************************************************************************
3195// Get the field offset for a given field token
3196//*****************************************************************************
3197__checkReturn
3198HRESULT MDInternalRW::GetFieldOffset(
3199 mdFieldDef fd, // [IN] fielddef
3200 ULONG *pulOffset) // [OUT] FieldOffset
3201{
3202 HRESULT hr = S_OK;
3203 FieldLayoutRec *pRec;
3204
3205 _ASSERTE(pulOffset);
3206
3207 RID iLayout;
3208
3209 LOCKREAD();
3210
3211 IfFailGo(m_pStgdb->m_MiniMd.FindFieldLayoutHelper(fd, &iLayout));
3212
3213 if (InvalidRid(iLayout))
3214 {
3215 hr = S_FALSE;
3216 goto ErrExit;
3217 }
3218
3219 IfFailGo(m_pStgdb->m_MiniMd.GetFieldLayoutRecord(iLayout, &pRec));
3220 *pulOffset = m_pStgdb->m_MiniMd.getOffSetOfFieldLayout(pRec);
3221 _ASSERTE(*pulOffset != ULONG_MAX);
3222
3223ErrExit:
3224 return hr;
3225} // MDInternalRW::GetFieldOffset
3226
3227//*****************************************************************************
3228// enum the next the field layout
3229//*****************************************************************************
3230__checkReturn
3231HRESULT MDInternalRW::GetClassLayoutNext(
3232 MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here
3233 mdFieldDef *pfd, // [OUT] field def
3234 ULONG *pulOffset) // [OUT] field offset or sequence
3235{
3236 HRESULT hr = S_OK;
3237
3238 _ASSERTE(pfd && pulOffset && pLayout);
3239
3240 RID iLayout2;
3241 FieldLayoutRec *pRec;
3242
3243 LOCKREAD();
3244
3245 while (pLayout->m_ridFieldCur < pLayout->m_ridFieldEnd)
3246 {
3247 RID fieldRid;
3248 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRid(pLayout->m_ridFieldCur, &fieldRid));
3249 mdFieldDef fd = TokenFromRid(fieldRid, mdtFieldDef);
3250 IfFailGo(m_pStgdb->m_MiniMd.FindFieldLayoutHelper(fd, &iLayout2));
3251 pLayout->m_ridFieldCur++;
3252 if (!InvalidRid(iLayout2))
3253 {
3254 IfFailGo(m_pStgdb->m_MiniMd.GetFieldLayoutRecord(iLayout2, &pRec));
3255 *pulOffset = m_pStgdb->m_MiniMd.getOffSetOfFieldLayout(pRec);
3256 _ASSERTE(*pulOffset != ULONG_MAX);
3257 *pfd = fd;
3258 goto ErrExit;
3259 }
3260 }
3261
3262 *pfd = mdFieldDefNil;
3263 hr = S_FALSE;
3264
3265 // fall through
3266
3267ErrExit:
3268 return hr;
3269} // MDInternalRW::GetClassLayoutNext
3270
3271
3272//*****************************************************************************
3273// return the field's native type signature
3274//*****************************************************************************
3275__checkReturn
3276HRESULT MDInternalRW::GetFieldMarshal( // return error if no native type associate with the token
3277 mdToken tk, // [IN] given fielddef or paramdef
3278 PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature
3279 ULONG *pcbNativeType) // [OUT] the count of bytes of *ppvNativeType
3280{
3281 // output parameters have to be supplied
3282 _ASSERTE(pcbNativeType);
3283
3284 RID rid;
3285 FieldMarshalRec *pFieldMarshalRec;
3286 HRESULT hr = NOERROR;
3287
3288 LOCKREAD();
3289
3290 // find the row containing the marshal definition for tk
3291 IfFailGo(m_pStgdb->m_MiniMd.FindFieldMarshalHelper(tk, &rid));
3292 if (InvalidRid(rid))
3293 {
3294 hr = CLDB_E_RECORD_NOTFOUND;
3295 goto ErrExit;
3296 }
3297 IfFailGo(m_pStgdb->m_MiniMd.GetFieldMarshalRecord(rid, &pFieldMarshalRec));
3298
3299 // get the native type
3300 IfFailGo(m_pStgdb->m_MiniMd.getNativeTypeOfFieldMarshal(pFieldMarshalRec, pSigNativeType, pcbNativeType));
3301ErrExit:
3302 return hr;
3303} // MDInternalRW::GetFieldMarshal
3304
3305
3306
3307//*****************************************
3308// property APIs
3309//*****************************************
3310
3311//*****************************************************************************
3312// Find property by name
3313//*****************************************************************************
3314__checkReturn
3315HRESULT MDInternalRW::FindProperty(
3316 mdTypeDef td, // [IN] given a typdef
3317 LPCSTR szPropName, // [IN] property name
3318 mdProperty *pProp) // [OUT] return property token
3319{
3320 HRESULT hr = NOERROR;
3321 LOCKREAD();
3322
3323 // output parameters have to be supplied
3324 _ASSERTE(TypeFromToken(td) == mdtTypeDef && pProp);
3325
3326 PropertyMapRec *pRec;
3327 PropertyRec *pProperty;
3328 RID ridPropertyMap;
3329 RID ridCur;
3330 RID ridEnd;
3331 LPCUTF8 szName;
3332
3333 IfFailGo(m_pStgdb->m_MiniMd.FindPropertyMapFor(RidFromToken(td), &ridPropertyMap));
3334 if (InvalidRid(ridPropertyMap))
3335 {
3336 // not found!
3337 hr = CLDB_E_RECORD_NOTFOUND;
3338 goto ErrExit;
3339 }
3340
3341 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pRec));
3342
3343 // get the starting/ending rid of properties of this typedef
3344 ridCur = m_pStgdb->m_MiniMd.getPropertyListOfPropertyMap(pRec);
3345 IfFailGo(m_pStgdb->m_MiniMd.getEndPropertyListOfPropertyMap(ridPropertyMap, &ridEnd));
3346
3347 for ( ; ridCur < ridEnd; ridCur ++ )
3348 {
3349 RID propertyRid;
3350 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRid(ridCur, &propertyRid));
3351 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRecord(propertyRid, &pProperty));
3352 IfFailGo(m_pStgdb->m_MiniMd.getNameOfProperty(pProperty, &szName));
3353 if ( strcmp(szName, szPropName) ==0 )
3354 {
3355 // Found the match. Set the output parameter and we are done.
3356 *pProp = TokenFromRid(propertyRid, mdtProperty);
3357 goto ErrExit;
3358 }
3359 }
3360
3361 // not found
3362 hr = CLDB_E_RECORD_NOTFOUND;
3363ErrExit:
3364 return hr;
3365} // MDInternalRW::FindProperty
3366
3367
3368
3369//*****************************************************************************
3370// return the properties of a property
3371//*****************************************************************************
3372__checkReturn
3373HRESULT MDInternalRW::GetPropertyProps(
3374 mdProperty prop, // [IN] property token
3375 LPCSTR *pszProperty, // [OUT] property name
3376 DWORD *pdwPropFlags, // [OUT] property flags.
3377 PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob
3378 ULONG *pcbSig) // [OUT] count of bytes in *ppvSig
3379{
3380 HRESULT hr = S_OK;
3381 LOCKREAD();
3382
3383 // output parameters have to be supplied
3384 _ASSERTE(TypeFromToken(prop) == mdtProperty);
3385
3386 PropertyRec *pProperty;
3387 ULONG cbSig;
3388
3389 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRecord(RidFromToken(prop), &pProperty));
3390
3391 // get name of the property
3392 if (pszProperty)
3393 {
3394 IfFailGo(m_pStgdb->m_MiniMd.getNameOfProperty(pProperty, pszProperty));
3395 }
3396
3397 // get the flags of property
3398 if (pdwPropFlags)
3399 *pdwPropFlags = m_pStgdb->m_MiniMd.getPropFlagsOfProperty(pProperty);
3400
3401 // get the type of the property
3402 if (ppvSig)
3403 {
3404 IfFailGo(m_pStgdb->m_MiniMd.getTypeOfProperty(pProperty, ppvSig, &cbSig));
3405 if (pcbSig)
3406 {
3407 *pcbSig = cbSig;
3408 }
3409 }
3410
3411ErrExit:
3412 return hr;
3413} // MDInternalRW::GetPropertyProps
3414
3415
3416//**********************************
3417//
3418// Event APIs
3419//
3420//**********************************
3421
3422//*****************************************************************************
3423// return an event by given the name
3424//*****************************************************************************
3425__checkReturn
3426HRESULT MDInternalRW::FindEvent(
3427 mdTypeDef td, // [IN] given a typdef
3428 LPCSTR szEventName, // [IN] event name
3429 mdEvent *pEvent) // [OUT] return event token
3430{
3431 HRESULT hr = NOERROR;
3432 LOCKREAD();
3433
3434 // output parameters have to be supplied
3435 _ASSERTE(TypeFromToken(td) == mdtTypeDef && pEvent);
3436
3437 EventMapRec *pRec;
3438 EventRec *pEventRec;
3439 RID ridEventMap;
3440 RID ridCur;
3441 RID ridEnd;
3442 LPCUTF8 szName;
3443
3444 IfFailGo(m_pStgdb->m_MiniMd.FindEventMapFor(RidFromToken(td), &ridEventMap));
3445 if (InvalidRid(ridEventMap))
3446 {
3447 // not found!
3448 hr = CLDB_E_RECORD_NOTFOUND;
3449 goto ErrExit;
3450 }
3451 IfFailGo(m_pStgdb->m_MiniMd.GetEventMapRecord(ridEventMap, &pRec));
3452
3453 // get the starting/ending rid of properties of this typedef
3454 ridCur = m_pStgdb->m_MiniMd.getEventListOfEventMap(pRec);
3455 IfFailGo(m_pStgdb->m_MiniMd.getEndEventListOfEventMap(ridEventMap, &ridEnd));
3456
3457 for (; ridCur < ridEnd; ridCur ++)
3458 {
3459 RID eventRid;
3460 IfFailGo(m_pStgdb->m_MiniMd.GetEventRid(ridCur, &eventRid));
3461 IfFailGo(m_pStgdb->m_MiniMd.GetEventRecord(eventRid, &pEventRec));
3462 IfFailGo(m_pStgdb->m_MiniMd.getNameOfEvent(pEventRec, &szName));
3463 if ( strcmp(szName, szEventName) ==0 )
3464 {
3465 // Found the match. Set the output parameter and we are done.
3466 *pEvent = TokenFromRid(eventRid, mdtEvent);
3467 goto ErrExit;
3468 }
3469 }
3470
3471 // not found
3472 hr = CLDB_E_RECORD_NOTFOUND;
3473ErrExit:
3474
3475 return hr;
3476} // MDInternalRW::FindEvent
3477
3478
3479//*****************************************************************************
3480// return the properties of an event
3481//*****************************************************************************
3482__checkReturn
3483HRESULT MDInternalRW::GetEventProps( // S_OK, S_FALSE, or error.
3484 mdEvent ev, // [IN] event token
3485 LPCSTR *pszEvent, // [OUT] Event name
3486 DWORD *pdwEventFlags, // [OUT] Event flags.
3487 mdToken *ptkEventType) // [OUT] EventType class
3488{
3489 HRESULT hr = S_OK;
3490 LOCKREAD();
3491 EventRec *pEvent;
3492
3493 // output parameters have to be supplied
3494 _ASSERTE(TypeFromToken(ev) == mdtEvent);
3495
3496 IfFailGo(m_pStgdb->m_MiniMd.GetEventRecord(RidFromToken(ev), &pEvent));
3497 if (pszEvent != NULL)
3498 {
3499 IfFailGo(m_pStgdb->m_MiniMd.getNameOfEvent(pEvent, pszEvent));
3500 }
3501 if (pdwEventFlags)
3502 *pdwEventFlags = m_pStgdb->m_MiniMd.getEventFlagsOfEvent(pEvent);
3503 if (ptkEventType)
3504 *ptkEventType = m_pStgdb->m_MiniMd.getEventTypeOfEvent(pEvent);
3505
3506ErrExit:
3507
3508 return hr;
3509} // MDInternalRW::GetEventProps
3510
3511//*****************************************************************************
3512// return the properties of a generic param
3513//*****************************************************************************
3514__checkReturn
3515HRESULT MDInternalRW::GetGenericParamProps( // S_OK or error.
3516 mdGenericParam rd, // [IN] The type parameter
3517 ULONG* pulSequence, // [OUT] Parameter sequence number
3518 DWORD* pdwAttr, // [OUT] Type parameter flags (for future use)
3519 mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef)
3520 DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use)
3521 LPCSTR *szName) // [OUT] The name
3522{
3523 HRESULT hr = NOERROR;
3524 GenericParamRec *pGenericParamRec = NULL;
3525
3526 // See if this version of the metadata can do Generics
3527 if (!m_pStgdb->m_MiniMd.SupportsGenerics())
3528 IfFailGo(CLDB_E_INCOMPATIBLE);
3529
3530 _ASSERTE(TypeFromToken(rd) == mdtGenericParam);
3531 if (TypeFromToken(rd) != mdtGenericParam)
3532 IfFailGo(CLDB_E_FILE_CORRUPT);
3533
3534 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamRecord(RidFromToken(rd), &pGenericParamRec));
3535
3536 if (pulSequence)
3537 *pulSequence = m_pStgdb->m_MiniMd.getNumberOfGenericParam(pGenericParamRec);
3538 if (pdwAttr)
3539 *pdwAttr = m_pStgdb->m_MiniMd.getFlagsOfGenericParam(pGenericParamRec);
3540 if (ptOwner)
3541 *ptOwner = m_pStgdb->m_MiniMd.getOwnerOfGenericParam(pGenericParamRec);
3542 if (szName != NULL)
3543 {
3544 IfFailGo(m_pStgdb->m_MiniMd.getNameOfGenericParam(pGenericParamRec, szName));
3545 }
3546
3547ErrExit:
3548 return hr;
3549} // MDInternalRW::GetGenericParamProps
3550
3551
3552//*****************************************************************************
3553// This routine gets the properties for the given GenericParamConstraint token.
3554//*****************************************************************************
3555__checkReturn
3556HRESULT MDInternalRW::GetGenericParamConstraintProps( // S_OK or error.
3557 mdGenericParamConstraint rd, // [IN] The constraint token
3558 mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained
3559 mdToken *ptkConstraintType) // [OUT] TypeDef/Ref/Spec constraint
3560{
3561 HRESULT hr = NOERROR;
3562 GenericParamConstraintRec *pGPCRec;
3563 RID ridRD = RidFromToken(rd);
3564
3565 // See if this version of the metadata can do Generics
3566 if (!m_pStgdb->m_MiniMd.SupportsGenerics())
3567 IfFailGo(CLDB_E_INCOMPATIBLE);
3568
3569 if((TypeFromToken(rd) == mdtGenericParamConstraint) && (ridRD != 0))
3570 {
3571 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamConstraintRecord(ridRD, &pGPCRec));
3572
3573 if (ptGenericParam)
3574 *ptGenericParam = TokenFromRid(m_pStgdb->m_MiniMd.getOwnerOfGenericParamConstraint(pGPCRec),mdtGenericParam);
3575 if (ptkConstraintType)
3576 *ptkConstraintType = m_pStgdb->m_MiniMd.getConstraintOfGenericParamConstraint(pGPCRec);
3577 }
3578 else
3579 hr = META_E_BAD_INPUT_PARAMETER;
3580
3581ErrExit:
3582 return hr;
3583} // MDInternalRW::GetGenericParamConstraintProps
3584
3585//*****************************************************************************
3586// Find methoddef of a particular associate with a property or an event
3587//*****************************************************************************
3588__checkReturn
3589HRESULT MDInternalRW::FindAssociate(
3590 mdToken evprop, // [IN] given a property or event token
3591 DWORD dwSemantics, // [IN] given a associate semantics(setter, getter, testdefault, reset)
3592 mdMethodDef *pmd) // [OUT] return method def token
3593{
3594 HRESULT hr = NOERROR;
3595 RID rid;
3596 MethodSemanticsRec *pMethodSemantics;
3597
3598 // output parameters have to be supplied
3599 _ASSERTE(pmd);
3600 _ASSERTE(TypeFromToken(evprop) == mdtEvent || TypeFromToken(evprop) == mdtProperty);
3601
3602 LOCKREAD();
3603
3604 hr = m_pStgdb->m_MiniMd.FindAssociateHelper(evprop, dwSemantics, &rid);
3605 if (SUCCEEDED(hr))
3606 {
3607 IfFailGo(m_pStgdb->m_MiniMd.GetMethodSemanticsRecord(rid, &pMethodSemantics));
3608 *pmd = m_pStgdb->m_MiniMd.getMethodOfMethodSemantics(pMethodSemantics);
3609 }
3610
3611ErrExit:
3612
3613 return hr;
3614} // MDInternalRW::FindAssociate
3615
3616
3617//*****************************************************************************
3618// get counts of methodsemantics associated with a particular property/event
3619//*****************************************************************************
3620__checkReturn
3621HRESULT MDInternalRW::EnumAssociateInit(
3622 mdToken evprop, // [IN] given a property or an event token
3623 HENUMInternal *phEnum) // [OUT] cursor to hold the query result
3624{
3625 HRESULT hr;
3626
3627 LOCKREAD();
3628
3629 // output parameters have to be supplied
3630 _ASSERTE(phEnum);
3631 _ASSERTE(TypeFromToken(evprop) == mdtEvent || TypeFromToken(evprop) == mdtProperty);
3632
3633 hr = m_pStgdb->m_MiniMd.FindMethodSemanticsHelper(evprop, phEnum);
3634
3635ErrExit:
3636 return hr;
3637} // MDInternalRW::EnumAssociateInit
3638
3639
3640//*****************************************************************************
3641// get all methodsemantics associated with a particular property/event
3642//*****************************************************************************
3643__checkReturn
3644HRESULT MDInternalRW::GetAllAssociates(
3645 HENUMInternal *phEnum, // [OUT] cursor to hold the query result
3646 ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output
3647 ULONG cAssociateRec) // [IN] size of the buffer
3648{
3649 HRESULT hr = S_OK;
3650 MethodSemanticsRec *pSemantics;
3651 RID ridCur;
3652 int index = 0;
3653
3654 LOCKREAD();
3655
3656 // <TODO>@FUTURE: rewrite the EnumAssociateInit and GetAllAssociates. Because we might add more properties and events.
3657 // Then we might resort MethodSemantics table. So this can be totally out of sync.</TODO>
3658
3659 _ASSERTE(phEnum && pAssociateRec);
3660 _ASSERTE(cAssociateRec == phEnum->m_ulCount);
3661
3662 // Convert from row pointers to RIDs.
3663 while (HENUMInternal::EnumNext(phEnum, (mdToken *)&ridCur))
3664 {
3665 IfFailGo(m_pStgdb->m_MiniMd.GetMethodSemanticsRecord(ridCur, &pSemantics));
3666
3667 pAssociateRec[index].m_memberdef = m_pStgdb->m_MiniMd.getMethodOfMethodSemantics(pSemantics);
3668 pAssociateRec[index].m_dwSemantics = m_pStgdb->m_MiniMd.getSemanticOfMethodSemantics(pSemantics);
3669 index++;
3670 }
3671
3672ErrExit:
3673
3674 return hr;
3675} // MDInternalRW::GetAllAssociates
3676
3677
3678//*****************************************************************************
3679// Get the Action and Permissions blob for a given PermissionSet.
3680//*****************************************************************************
3681__checkReturn
3682HRESULT MDInternalRW::GetPermissionSetProps(
3683 mdPermission pm, // [IN] the permission token.
3684 DWORD *pdwAction, // [OUT] CorDeclSecurity.
3685 void const **ppvPermission, // [OUT] permission blob.
3686 ULONG *pcbPermission) // [OUT] count of bytes of pvPermission.
3687{
3688 HRESULT hr = S_OK;
3689 _ASSERTE(TypeFromToken(pm) == mdtPermission);
3690 _ASSERTE(pdwAction && ppvPermission && pcbPermission);
3691
3692 DeclSecurityRec *pPerm;
3693 LOCKREAD();
3694
3695 IfFailGo(m_pStgdb->m_MiniMd.GetDeclSecurityRecord(RidFromToken(pm), &pPerm));
3696 *pdwAction = m_pStgdb->m_MiniMd.getActionOfDeclSecurity(pPerm);
3697 IfFailGo(m_pStgdb->m_MiniMd.getPermissionSetOfDeclSecurity(pPerm, reinterpret_cast<const BYTE **>(ppvPermission), pcbPermission));
3698
3699ErrExit:
3700
3701 return hr;
3702} // MDInternalRW::GetPermissionSetProps
3703
3704
3705//*****************************************************************************
3706// Get the String given the String token.
3707// Return a pointer to the string, or NULL in case of error.
3708//*****************************************************************************
3709__checkReturn
3710HRESULT
3711MDInternalRW::GetUserString( // Offset into the string blob heap.
3712 mdString stk, // [IN] the string token.
3713 ULONG *pcchStringSize, // [OUT] count of characters in the string.
3714 BOOL *pfIs80Plus, // [OUT] specifies where there are extended characters >= 0x80.
3715 LPCWSTR *pwszUserString)
3716{
3717 HRESULT hr;
3718 LPWSTR wszTmp;
3719
3720 // no need to lock this function.
3721
3722 if (pfIs80Plus != NULL)
3723 {
3724 *pfIs80Plus = FALSE;
3725 }
3726 *pwszUserString = NULL;
3727 *pcchStringSize = 0;
3728
3729 _ASSERTE(pcchStringSize != NULL);
3730 MetaData::DataBlob userString;
3731 IfFailRet(m_pStgdb->m_MiniMd.GetUserString(RidFromToken(stk), &userString));
3732
3733 wszTmp = reinterpret_cast<LPWSTR>(userString.GetDataPointer());
3734
3735 *pcchStringSize = userString.GetSize() / sizeof(WCHAR);
3736
3737 if (userString.IsEmpty())
3738 {
3739 *pwszUserString = NULL;
3740 return S_OK;
3741 }
3742
3743 if (pfIs80Plus != NULL)
3744 {
3745 if (userString.GetSize() % sizeof(WCHAR) == 0)
3746 {
3747 *pfIs80Plus = TRUE; // no indicator, presume the worst
3748 }
3749 // Return the user string terminator (contains value fIs80Plus)
3750 *pfIs80Plus = *(reinterpret_cast<PBYTE>(wszTmp + *pcchStringSize));
3751 }
3752
3753 *pwszUserString = wszTmp;
3754 return S_OK;
3755} // MDInternalRW::GetUserString
3756
3757//*****************************************************************************
3758// Get the properties for the given Assembly token.
3759//*****************************************************************************
3760__checkReturn
3761HRESULT MDInternalRW::GetAssemblyProps(
3762 mdAssembly mda, // [IN] The Assembly for which to get the properties.
3763 const void **ppbPublicKey, // [OUT] Pointer to the public key.
3764 ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key.
3765 ULONG *pulHashAlgId, // [OUT] Hash Algorithm.
3766 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3767 AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData.
3768 DWORD *pdwAssemblyFlags) // [OUT] Flags.
3769{
3770 AssemblyRec *pRecord;
3771 HRESULT hr = S_OK;
3772 LOCKREAD();
3773
3774 _ASSERTE(TypeFromToken(mda) == mdtAssembly && RidFromToken(mda));
3775 IfFailGo(m_pStgdb->m_MiniMd.GetAssemblyRecord(RidFromToken(mda), &pRecord));
3776
3777 if (ppbPublicKey != NULL)
3778 {
3779 IfFailGo(m_pStgdb->m_MiniMd.getPublicKeyOfAssembly(pRecord, reinterpret_cast<const BYTE **>(ppbPublicKey), pcbPublicKey));
3780 }
3781 if (pulHashAlgId)
3782 *pulHashAlgId = m_pStgdb->m_MiniMd.getHashAlgIdOfAssembly(pRecord);
3783 if (pszName != NULL)
3784 {
3785 IfFailGo(m_pStgdb->m_MiniMd.getNameOfAssembly(pRecord, pszName));
3786 }
3787 if (pMetaData)
3788 {
3789 pMetaData->usMajorVersion = m_pStgdb->m_MiniMd.getMajorVersionOfAssembly(pRecord);
3790 pMetaData->usMinorVersion = m_pStgdb->m_MiniMd.getMinorVersionOfAssembly(pRecord);
3791 pMetaData->usBuildNumber = m_pStgdb->m_MiniMd.getBuildNumberOfAssembly(pRecord);
3792 pMetaData->usRevisionNumber = m_pStgdb->m_MiniMd.getRevisionNumberOfAssembly(pRecord);
3793 IfFailGo(m_pStgdb->m_MiniMd.getLocaleOfAssembly(pRecord, &pMetaData->szLocale));
3794 pMetaData->ulProcessor = 0;
3795 pMetaData->ulOS = 0;
3796 }
3797 if (pdwAssemblyFlags)
3798 {
3799 *pdwAssemblyFlags = m_pStgdb->m_MiniMd.getFlagsOfAssembly(pRecord);
3800
3801 // Turn on the afPublicKey if PublicKey blob is not empty
3802 DWORD cbPublicKey;
3803 const BYTE *pbPublicKey;
3804 IfFailGo(m_pStgdb->m_MiniMd.getPublicKeyOfAssembly(pRecord, &pbPublicKey, &cbPublicKey));
3805 if (cbPublicKey)
3806 *pdwAssemblyFlags |= afPublicKey;
3807 }
3808
3809ErrExit:
3810 return hr;
3811
3812} // MDInternalRW::GetAssemblyProps
3813
3814//*****************************************************************************
3815// Get the properties for the given AssemblyRef token.
3816//*****************************************************************************
3817__checkReturn
3818HRESULT MDInternalRW::GetAssemblyRefProps(
3819 mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties.
3820 const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token.
3821 ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token.
3822 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3823 AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData.
3824 const void **ppbHashValue, // [OUT] Hash blob.
3825 ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob.
3826 DWORD *pdwAssemblyRefFlags) // [OUT] Flags.
3827{
3828 AssemblyRefRec *pRecord;
3829 HRESULT hr = S_OK;
3830
3831 LOCKREAD();
3832
3833 _ASSERTE(TypeFromToken(mdar) == mdtAssemblyRef && RidFromToken(mdar));
3834 IfFailGo(m_pStgdb->m_MiniMd.GetAssemblyRefRecord(RidFromToken(mdar), &pRecord));
3835
3836 if (ppbPublicKeyOrToken != NULL)
3837 {
3838 IfFailGo(m_pStgdb->m_MiniMd.getPublicKeyOrTokenOfAssemblyRef(pRecord, reinterpret_cast<const BYTE **>(ppbPublicKeyOrToken), pcbPublicKeyOrToken));
3839 }
3840 if (pszName != NULL)
3841 {
3842 IfFailGo(m_pStgdb->m_MiniMd.getNameOfAssemblyRef(pRecord, pszName));
3843 }
3844 if (pMetaData)
3845 {
3846 pMetaData->usMajorVersion = m_pStgdb->m_MiniMd.getMajorVersionOfAssemblyRef(pRecord);
3847 pMetaData->usMinorVersion = m_pStgdb->m_MiniMd.getMinorVersionOfAssemblyRef(pRecord);
3848 pMetaData->usBuildNumber = m_pStgdb->m_MiniMd.getBuildNumberOfAssemblyRef(pRecord);
3849 pMetaData->usRevisionNumber = m_pStgdb->m_MiniMd.getRevisionNumberOfAssemblyRef(pRecord);
3850 IfFailGo(m_pStgdb->m_MiniMd.getLocaleOfAssemblyRef(pRecord, &pMetaData->szLocale));
3851 pMetaData->ulProcessor = 0;
3852 pMetaData->ulOS = 0;
3853 }
3854 if (ppbHashValue != NULL)
3855 {
3856 IfFailGo(m_pStgdb->m_MiniMd.getHashValueOfAssemblyRef(pRecord, reinterpret_cast<const BYTE **>(ppbHashValue), pcbHashValue));
3857 }
3858 if (pdwAssemblyRefFlags)
3859 *pdwAssemblyRefFlags = m_pStgdb->m_MiniMd.getFlagsOfAssemblyRef(pRecord);
3860
3861ErrExit:
3862 return hr;
3863} // MDInternalRW::GetAssemblyRefProps
3864
3865//*****************************************************************************
3866// Get the properties for the given File token.
3867//*****************************************************************************
3868__checkReturn
3869HRESULT MDInternalRW::GetFileProps(
3870 mdFile mdf, // [IN] The File for which to get the properties.
3871 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3872 const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob.
3873 ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob.
3874 DWORD *pdwFileFlags) // [OUT] Flags.
3875{
3876 FileRec *pRecord;
3877 HRESULT hr = S_OK;
3878
3879 LOCKREAD();
3880
3881 _ASSERTE(TypeFromToken(mdf) == mdtFile && RidFromToken(mdf));
3882 IfFailGo(m_pStgdb->m_MiniMd.GetFileRecord(RidFromToken(mdf), &pRecord));
3883
3884 if (pszName != NULL)
3885 {
3886 IfFailGo(m_pStgdb->m_MiniMd.getNameOfFile(pRecord, pszName));
3887 }
3888 if (ppbHashValue != NULL)
3889 {
3890 IfFailGo(m_pStgdb->m_MiniMd.getHashValueOfFile(pRecord, reinterpret_cast<const BYTE **>(ppbHashValue), pcbHashValue));
3891 }
3892 if (pdwFileFlags)
3893 *pdwFileFlags = m_pStgdb->m_MiniMd.getFlagsOfFile(pRecord);
3894
3895ErrExit:
3896 return hr;
3897} // MDInternalRW::GetFileProps
3898
3899//*****************************************************************************
3900// Get the properties for the given ExportedType token.
3901//*****************************************************************************
3902__checkReturn
3903HRESULT MDInternalRW::GetExportedTypeProps(
3904 mdExportedType mdct, // [IN] The ExportedType for which to get the properties.
3905 LPCSTR *pszNamespace, // [OUT] Buffer to fill with name.
3906 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3907 mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
3908 mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file.
3909 DWORD *pdwExportedTypeFlags) // [OUT] Flags.
3910{
3911 ExportedTypeRec *pRecord;
3912 HRESULT hr = S_OK;
3913
3914 LOCKREAD();
3915
3916 _ASSERTE(TypeFromToken(mdct) == mdtExportedType && RidFromToken(mdct));
3917 IfFailGo(m_pStgdb->m_MiniMd.GetExportedTypeRecord(RidFromToken(mdct), &pRecord));
3918
3919 if (pszNamespace != NULL)
3920 {
3921 IfFailGo(m_pStgdb->m_MiniMd.getTypeNamespaceOfExportedType(pRecord, pszNamespace));
3922 }
3923 if (pszName != NULL)
3924 {
3925 IfFailGo(m_pStgdb->m_MiniMd.getTypeNameOfExportedType(pRecord, pszName));
3926 }
3927 if (ptkImplementation)
3928 *ptkImplementation = m_pStgdb->m_MiniMd.getImplementationOfExportedType(pRecord);
3929 if (ptkTypeDef)
3930 *ptkTypeDef = m_pStgdb->m_MiniMd.getTypeDefIdOfExportedType(pRecord);
3931 if (pdwExportedTypeFlags)
3932 *pdwExportedTypeFlags = m_pStgdb->m_MiniMd.getFlagsOfExportedType(pRecord);
3933
3934ErrExit:
3935 return hr;
3936} // MDInternalRW::GetExportedTypeProps
3937
3938//*****************************************************************************
3939// Get the properties for the given Resource token.
3940//*****************************************************************************
3941__checkReturn
3942HRESULT MDInternalRW::GetManifestResourceProps(
3943 mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties.
3944 LPCSTR *pszName, // [OUT] Buffer to fill with name.
3945 mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType.
3946 DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file.
3947 DWORD *pdwResourceFlags) // [OUT] Flags.
3948{
3949 ManifestResourceRec *pRecord;
3950 HRESULT hr = S_OK;
3951
3952 LOCKREAD();
3953
3954 _ASSERTE(TypeFromToken(mdmr) == mdtManifestResource && RidFromToken(mdmr));
3955 IfFailGo(m_pStgdb->m_MiniMd.GetManifestResourceRecord(RidFromToken(mdmr), &pRecord));
3956
3957 if (pszName != NULL)
3958 {
3959 IfFailGo(m_pStgdb->m_MiniMd.getNameOfManifestResource(pRecord, pszName));
3960 }
3961 if (ptkImplementation)
3962 *ptkImplementation = m_pStgdb->m_MiniMd.getImplementationOfManifestResource(pRecord);
3963 if (pdwOffset)
3964 *pdwOffset = m_pStgdb->m_MiniMd.getOffsetOfManifestResource(pRecord);
3965 if (pdwResourceFlags)
3966 *pdwResourceFlags = m_pStgdb->m_MiniMd.getFlagsOfManifestResource(pRecord);
3967
3968ErrExit:
3969 return hr;
3970} // MDInternalRW::GetManifestResourceProps
3971
3972//*****************************************************************************
3973// Find the ExportedType given the name.
3974//*****************************************************************************
3975__checkReturn
3976STDMETHODIMP MDInternalRW::FindExportedTypeByName( // S_OK or error
3977 LPCSTR szNamespace, // [IN] Namespace of the ExportedType.
3978 LPCSTR szName, // [IN] Name of the ExportedType.
3979 mdExportedType tkEnclosingType, // [IN] Enclosing ExportedType.
3980 mdExportedType *pmct) // [OUT] Put ExportedType token here.
3981{
3982 _ASSERTE(szName && pmct);
3983 HRESULT hr = S_OK;
3984 LOCKREADIFFAILRET();
3985
3986 IMetaModelCommon *pCommon = static_cast<IMetaModelCommon*>(&m_pStgdb->m_MiniMd);
3987 return pCommon->CommonFindExportedType(szNamespace, szName, tkEnclosingType, pmct);
3988} // MDInternalRW::FindExportedTypeByName
3989
3990//*****************************************************************************
3991// Find the ManifestResource given the name.
3992//*****************************************************************************
3993__checkReturn
3994STDMETHODIMP MDInternalRW::FindManifestResourceByName(// S_OK or error
3995 LPCSTR szName, // [IN] Name of the resource.
3996 mdManifestResource *pmmr) // [OUT] Put ManifestResource token here.
3997{
3998 _ASSERTE(szName && pmmr);
3999
4000 ManifestResourceRec *pRecord;
4001 ULONG cRecords; // Count of records.
4002 LPCUTF8 szNameTmp = 0; // Name obtained from the database.
4003 ULONG i;
4004 HRESULT hr = S_OK;
4005
4006 LOCKREAD();
4007
4008 cRecords = m_pStgdb->m_MiniMd.getCountManifestResources();
4009
4010 // Search for the ExportedType.
4011 for (i = 1; i <= cRecords; i++)
4012 {
4013 IfFailGo(m_pStgdb->m_MiniMd.GetManifestResourceRecord(i, &pRecord));
4014 IfFailGo(m_pStgdb->m_MiniMd.getNameOfManifestResource(pRecord, &szNameTmp));
4015 if (! strcmp(szName, szNameTmp))
4016 {
4017 *pmmr = TokenFromRid(i, mdtManifestResource);
4018 goto ErrExit;
4019 }
4020 }
4021 hr = CLDB_E_RECORD_NOTFOUND;
4022ErrExit:
4023
4024 return hr;
4025} // MDInternalRW::FindManifestResourceByName
4026
4027//*****************************************************************************
4028// Get the Assembly token from the given scope.
4029//*****************************************************************************
4030__checkReturn
4031HRESULT MDInternalRW::GetAssemblyFromScope( // S_OK or error
4032 mdAssembly *ptkAssembly) // [OUT] Put token here.
4033{
4034 _ASSERTE(ptkAssembly);
4035
4036 if (m_pStgdb->m_MiniMd.getCountAssemblys())
4037 {
4038 *ptkAssembly = TokenFromRid(1, mdtAssembly);
4039 return S_OK;
4040 }
4041 else
4042 return CLDB_E_RECORD_NOTFOUND;
4043} // MDInternalRW::GetAssemblyFromScope
4044
4045//*******************************************************************************
4046// return properties regarding a TypeSpec
4047//*******************************************************************************
4048//*******************************************************************************
4049// return properties regarding a TypeSpec
4050//*******************************************************************************
4051__checkReturn
4052HRESULT MDInternalRW::GetTypeSpecFromToken( // S_OK or error.
4053 mdTypeSpec typespec, // [IN] Signature token.
4054 PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token.
4055 ULONG *pcbSig) // [OUT] return size of signature.
4056{
4057 HRESULT hr = NOERROR;
4058
4059 _ASSERTE(TypeFromToken(typespec) == mdtTypeSpec);
4060 _ASSERTE(ppvSig && pcbSig);
4061
4062 if (!IsValidToken(typespec))
4063 return E_INVALIDARG;
4064
4065 TypeSpecRec *pRec;
4066 IfFailRet(m_pStgdb->m_MiniMd.GetTypeSpecRecord(RidFromToken(typespec), &pRec));
4067
4068 if (pRec == NULL)
4069 return CLDB_E_FILE_CORRUPT;
4070
4071 IfFailRet(m_pStgdb->m_MiniMd.getSignatureOfTypeSpec(pRec, ppvSig, pcbSig));
4072
4073 return hr;
4074} // MDInternalRW::GetTypeSpecFromToken
4075
4076
4077//*****************************************************************************
4078// Return contents of Pinvoke given the forwarded member token.
4079//*****************************************************************************
4080__checkReturn
4081HRESULT MDInternalRW::GetPinvokeMap(
4082 mdToken tk, // [IN] FieldDef, MethodDef or MethodImpl.
4083 DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
4084 LPCSTR *pszImportName, // [OUT] Import name.
4085 mdModuleRef *pmrImportDLL) // [OUT] ModuleRef token for the target DLL.
4086{
4087 ImplMapRec *pRecord;
4088 ULONG iRecord;
4089 HRESULT hr = S_OK;
4090
4091 LOCKREAD();
4092
4093 IfFailGo(m_pStgdb->m_MiniMd.FindImplMapHelper(tk, &iRecord));
4094 if (InvalidRid(iRecord))
4095 {
4096 hr = CLDB_E_RECORD_NOTFOUND;
4097 goto ErrExit;
4098 }
4099 else
4100 IfFailGo(m_pStgdb->m_MiniMd.GetImplMapRecord(iRecord, &pRecord));
4101
4102 if (pdwMappingFlags)
4103 *pdwMappingFlags = m_pStgdb->m_MiniMd.getMappingFlagsOfImplMap(pRecord);
4104 if (pszImportName != NULL)
4105 {
4106 IfFailGo(m_pStgdb->m_MiniMd.getImportNameOfImplMap(pRecord, pszImportName));
4107 }
4108 if (pmrImportDLL)
4109 *pmrImportDLL = m_pStgdb->m_MiniMd.getImportScopeOfImplMap(pRecord);
4110ErrExit:
4111 return hr;
4112} // MDInternalRW::GetPinvokeMap
4113
4114//*****************************************************************************
4115// convert a text signature to com format
4116//*****************************************************************************
4117__checkReturn
4118HRESULT MDInternalRW::ConvertTextSigToComSig(// Return hresult.
4119 BOOL fCreateTrIfNotFound, // create typeref if not found or not
4120 LPCSTR pSignature, // class file format signature
4121 CQuickBytes *pqbNewSig, // [OUT] place holder for COM+ signature
4122 ULONG *pcbCount) // [OUT] the result size of signature
4123{
4124 return E_NOTIMPL;
4125} // _ConvertTextSigToComSig
4126
4127//*****************************************************************************
4128// This is a way for the EE to associate some data with this RW metadata to
4129// be released when this RW goes away. This is useful when a RO metadata is
4130// converted to RW, because arbitrary threads can be executing in the RO.
4131// So, we hold onto the RO here, and when the module shuts down, we release it.
4132//*****************************************************************************
4133__checkReturn
4134HRESULT MDInternalRW::SetUserContextData(// S_OK or E_NOTIMPL
4135 IUnknown *pIUnk) // The user context.
4136{
4137 // Only one chance to do this.
4138 if (m_pUserUnk)
4139 return E_UNEXPECTED;
4140 m_pUserUnk = pIUnk;
4141 return S_OK;
4142} // MDInternalRW::SetUserContextData
4143
4144//*****************************************************************************
4145// determine if a token is valid or not
4146//*****************************************************************************
4147BOOL MDInternalRW::IsValidToken( // True or False.
4148 mdToken tk) // [IN] Given token.
4149{
4150 RID rid = RidFromToken(tk);
4151 // no need to lock on this function.
4152 if (rid == 0)
4153 {
4154 return FALSE;
4155 }
4156 switch (TypeFromToken(tk))
4157 {
4158 case mdtModule:
4159 // can have only one module record
4160 return (rid <= m_pStgdb->m_MiniMd.getCountModules());
4161 case mdtTypeRef:
4162 return (rid <= m_pStgdb->m_MiniMd.getCountTypeRefs());
4163 case mdtTypeDef:
4164 return (rid <= m_pStgdb->m_MiniMd.getCountTypeDefs());
4165 case mdtFieldDef:
4166 return (rid <= m_pStgdb->m_MiniMd.getCountFields());
4167 case mdtMethodDef:
4168 return (rid <= m_pStgdb->m_MiniMd.getCountMethods());
4169 case mdtParamDef:
4170 return (rid <= m_pStgdb->m_MiniMd.getCountParams());
4171 case mdtInterfaceImpl:
4172 return (rid <= m_pStgdb->m_MiniMd.getCountInterfaceImpls());
4173 case mdtMemberRef:
4174 return (rid <= m_pStgdb->m_MiniMd.getCountMemberRefs());
4175 case mdtCustomAttribute:
4176 return (rid <= m_pStgdb->m_MiniMd.getCountCustomAttributes());
4177 case mdtPermission:
4178 return (rid <= m_pStgdb->m_MiniMd.getCountDeclSecuritys());
4179 case mdtSignature:
4180 return (rid <= m_pStgdb->m_MiniMd.getCountStandAloneSigs());
4181 case mdtEvent:
4182 return (rid <= m_pStgdb->m_MiniMd.getCountEvents());
4183 case mdtProperty:
4184 return (rid <= m_pStgdb->m_MiniMd.getCountPropertys());
4185 case mdtModuleRef:
4186 return (rid <= m_pStgdb->m_MiniMd.getCountModuleRefs());
4187 case mdtTypeSpec:
4188 return (rid <= m_pStgdb->m_MiniMd.getCountTypeSpecs());
4189 case mdtAssembly:
4190 return (rid <= m_pStgdb->m_MiniMd.getCountAssemblys());
4191 case mdtAssemblyRef:
4192 return (rid <= m_pStgdb->m_MiniMd.getCountAssemblyRefs());
4193 case mdtFile:
4194 return (rid <= m_pStgdb->m_MiniMd.getCountFiles());
4195 case mdtExportedType:
4196 return (rid <= m_pStgdb->m_MiniMd.getCountExportedTypes());
4197 case mdtManifestResource:
4198 return (rid <= m_pStgdb->m_MiniMd.getCountManifestResources());
4199 case mdtMethodSpec:
4200 return (rid <= m_pStgdb->m_MiniMd.getCountMethodSpecs());
4201 case mdtString:
4202 // need to check the user string heap
4203 return m_pStgdb->m_MiniMd.m_UserStringHeap.IsValidIndex(rid);
4204 }
4205 return FALSE;
4206} // MDInternalRW::IsValidToken
4207
4208mdModule MDInternalRW::GetModuleFromScope(void)
4209{
4210 return TokenFromRid(1, mdtModule);
4211} // MDInternalRW::GetModuleFromScope
4212
4213//*****************************************************************************
4214// Given a MetaData with ENC changes, apply those changes to this MetaData.
4215//*****************************************************************************
4216__checkReturn
4217HRESULT MDInternalRW::ApplyEditAndContinue( // S_OK or error.
4218 MDInternalRW *pDeltaMD) // Interface to MD with the ENC delta.
4219{
4220 HRESULT hr; // A result.
4221 // Get the MiniMd on the delta.
4222
4223 LOCKWRITEIFFAILRET();
4224
4225 CMiniMdRW &mdDelta = pDeltaMD->m_pStgdb->m_MiniMd;
4226 CMiniMdRW &mdBase = m_pStgdb->m_MiniMd;
4227
4228
4229 IfFailGo(mdBase.ConvertToRW());
4230 IfFailGo(mdBase.ApplyDelta(mdDelta));
4231ErrExit:
4232 return hr;
4233} // MDInternalRW::ApplyEditAndContinue
4234
4235//*****************************************************************************
4236// Given a MetaData with ENC changes, enumerate the changed tokens.
4237//*****************************************************************************
4238__checkReturn
4239HRESULT MDInternalRW::EnumDeltaTokensInit( // return hresult
4240 HENUMInternal *phEnum) // Enumerator to initialize.
4241{
4242 HRESULT hr = S_OK; // A result.
4243 ULONG index; // Loop control.
4244 ENCLogRec *pRec; // An ENCLog record.
4245
4246 // Vars for query.
4247 _ASSERTE(phEnum);
4248 memset(phEnum, 0, sizeof(HENUMInternal));
4249
4250 // cache the tkKind and the scope
4251 phEnum->m_tkKind = 0;
4252
4253 phEnum->m_EnumType = MDSimpleEnum;
4254
4255 HENUMInternal::InitDynamicArrayEnum(phEnum);
4256 for (index = 1; index <= m_pStgdb->m_MiniMd.m_Schema.m_cRecs[TBL_ENCLog]; ++index)
4257 {
4258 // Get the token type; see if it is a real token.
4259 IfFailGo(m_pStgdb->m_MiniMd.GetENCLogRecord(index, &pRec));
4260 if (CMiniMdRW::IsRecId(pRec->GetToken()))
4261 continue;
4262 // If there is a function code, that means that this flags a child-record
4263 // addition. The child record will generate its own token, so did the
4264 // parent, so skip the record.
4265 if (pRec->GetFuncCode())
4266 continue;
4267
4268 IfFailGo( HENUMInternal::AddElementToEnum(
4269 phEnum,
4270 pRec->GetToken()));
4271 }
4272
4273ErrExit:
4274 // we are done
4275 return hr;
4276} // MDInternalRW::EnumDeltaTokensInit
4277
4278
4279//*****************************************************************************
4280// Static function to apply a delta md. This is what the EE calls to apply
4281// the metadata updates from an update PE to live metadata.
4282// <TODO>MAY REPLACE THE IMDInternalImport POINTER!</TODO>
4283//*****************************************************************************
4284__checkReturn
4285HRESULT MDApplyEditAndContinue( // S_OK or error.
4286 IMDInternalImport **ppIMD, // [in, out] The metadata to be updated.
4287 IMDInternalImportENC *pDeltaMD) // [in] The delta metadata.
4288{
4289 HRESULT hr; // A result.
4290 IMDInternalImportENC *pENC; // ENC interface on the metadata.
4291
4292 // If the input metadata isn't RW, convert it.
4293 hr = (*ppIMD)->QueryInterface(IID_IMDInternalImportENC, (void**)&pENC);
4294 if (FAILED(hr))
4295 {
4296 IfFailGo(ConvertRO2RW(*ppIMD, IID_IMDInternalImportENC, (void**)&pENC));
4297 // Replace the old interface pointer with the ENC one.
4298 (*ppIMD)->Release();
4299 IfFailGo(pENC->QueryInterface(IID_IMDInternalImport, (void**)ppIMD));
4300 }
4301
4302 // Apply the delta to the input metadata.
4303 hr = pENC->ApplyEditAndContinue(static_cast<MDInternalRW*>(pDeltaMD));
4304
4305ErrExit:
4306 if (pENC)
4307 pENC->Release();
4308 return hr;
4309} // MDApplyEditAndContinue
4310
4311//*****************************************************************************
4312// Given a scope, return the table size and table ptr for a given index
4313//*****************************************************************************
4314__checkReturn
4315HRESULT MDInternalRW::GetTableInfoWithIndex( // return size
4316 ULONG index, // [IN] pass in the index
4317 void **pTable, // [OUT] pointer to table at index
4318 void **pTableSize) // [OUT] size of table at index
4319{
4320 _ASSERTE(!"NYI");
4321 return E_NOTIMPL;
4322}
4323
4324//*****************************************************************************
4325// Given a delta metadata byte stream, apply the changes to the current metadata
4326// object returning the resulting metadata object in ppv
4327//*****************************************************************************
4328__checkReturn
4329HRESULT MDInternalRW::ApplyEditAndContinue(
4330 void *pDeltaMD, // [IN] the delta metadata
4331 ULONG cbDeltaMD, // [IN] length of pData
4332 IMDInternalImport **ppv) // [OUT] the resulting metadata interface
4333{
4334 _ASSERTE(pDeltaMD);
4335 _ASSERTE(ppv);
4336
4337 // debugging-specific usages don't need SO hardening
4338 SO_NOT_MAINLINE_FUNCTION;
4339
4340 HRESULT hr = E_FAIL;
4341 IMDInternalImportENC *pDeltaMDImport = NULL;
4342
4343 IfFailGo(GetInternalWithRWFormat(pDeltaMD, cbDeltaMD, 0, IID_IMDInternalImportENC, (void**)&pDeltaMDImport));
4344
4345 *ppv = this;
4346 IfFailGo(MDApplyEditAndContinue(ppv, pDeltaMDImport));
4347
4348ErrExit:
4349 if (pDeltaMDImport)
4350 pDeltaMDImport->Release();
4351
4352 return hr;
4353} // MDInternalRW::ApplyEditAndContinue
4354
4355#endif //FEATURE_METADATA_INTERNAL_APIS
4356