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// Import.cpp
6//
7
8//
9// Methods of code:RegMeta class which implement public API interfaces:
10// * code:IMetaDataImport, and
11// * code:IMetaDataImport2.
12//
13//*****************************************************************************
14#include "stdafx.h"
15#include "regmeta.h"
16#include "metadata.h"
17#include "corerror.h"
18#include "mdutil.h"
19#include "rwutil.h"
20#include "corpriv.h"
21#include "importhelper.h"
22#include "mdlog.h"
23#include "mdperf.h"
24#include "stgio.h"
25
26//*****************************************************************************
27// Enumerate over all the Methods in a TypeDef.
28//*****************************************************************************
29STDMETHODIMP RegMeta::EnumMembers( // S_OK, S_FALSE, or error.
30 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
31 mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
32 mdToken rMembers[], // [OUT] Put MemberDefs here.
33 ULONG cMax, // [IN] Max MemberDefs to put.
34 ULONG *pcTokens) // [OUT] Put # put here.
35{
36 HRESULT hr = NOERROR;
37
38 BEGIN_ENTRYPOINT_NOTHROW;
39
40 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
41 ULONG ridStartMethod;
42 ULONG ridEndMethod;
43 ULONG ridStartField;
44 ULONG ridEndField;
45 ULONG index;
46 ULONG indexField;
47 TypeDefRec *pRec;
48 HENUMInternal *pEnum = *ppmdEnum;
49
50 LOG((LOGMD, "MD RegMeta::EnumMembers(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
51 phEnum, cl, rMembers, cMax, pcTokens));
52
53 START_MD_PERF();
54 LOCKREAD();
55
56 if ( pEnum == 0 )
57 {
58 // instantiating a new ENUM
59 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
60
61 if ( IsGlobalMethodParentTk(cl) )
62 {
63 cl = m_tdModule;
64 }
65
66 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(cl), &pRec));
67
68 ridStartMethod = m_pStgdb->m_MiniMd.getMethodListOfTypeDef(pRec);
69 IfFailGo(m_pStgdb->m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(cl), &ridEndMethod));
70
71 ridStartField = m_pStgdb->m_MiniMd.getFieldListOfTypeDef(pRec);
72 IfFailGo(m_pStgdb->m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(cl), &ridEndField));
73
74
75 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtMethodDef, &pEnum) );
76
77 // add all methods to the dynamic array
78 for (index = ridStartMethod; index < ridEndMethod; index++ )
79 {
80 RID rid;
81 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
82 IfFailGo(HENUMInternal::AddElementToEnum(
83 pEnum,
84 TokenFromRid(rid, mdtMethodDef)));
85 }
86
87 // add all fields to the dynamic array
88 for (indexField = ridStartField; indexField < ridEndField; indexField++ )
89 {
90 RID rid;
91 IfFailGo(pMiniMd->GetFieldRid(indexField, &rid));
92 IfFailGo(HENUMInternal::AddElementToEnum(
93 pEnum,
94 TokenFromRid(rid, mdtFieldDef)));
95 }
96
97 // set the output parameter
98 *ppmdEnum = pEnum;
99 }
100
101 // fill the output token buffer
102 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rMembers, pcTokens);
103
104ErrExit:
105 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
106
107 STOP_MD_PERF(EnumMembers);
108
109 END_ENTRYPOINT_NOTHROW;
110
111 return hr;
112} // STDMETHODIMP RegMeta::EnumMembers()
113
114//*****************************************************************************
115// Enumerate over all the Methods in a TypeDef that has szName
116//*****************************************************************************
117STDMETHODIMP RegMeta::EnumMembersWithName( // S_OK, S_FALSE, or error.
118 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
119 mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
120 LPCWSTR szName, // [IN] Limit results to those with this name.
121 mdToken rMembers[], // [OUT] Put MemberDefs here.
122 ULONG cMax, // [IN] Max MemberDefs to put.
123 ULONG *pcTokens) // [OUT] Put # put here.
124{
125 HRESULT hr = NOERROR;
126
127 BEGIN_ENTRYPOINT_NOTHROW;
128
129 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
130 ULONG ridStart;
131 ULONG ridEnd;
132 ULONG index;
133 TypeDefRec *pRec;
134 MethodRec *pMethod;
135 FieldRec *pField;
136 HENUMInternal *pEnum = *ppmdEnum;
137 LPUTF8 szNameUtf8;
138 UTF8STR(szName, szNameUtf8);
139 LPCUTF8 szNameUtf8Tmp;
140
141 LOG((LOGMD, "MD RegMeta::EnumMembersWithName(0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
142 phEnum, cl, MDSTR(szName), rMembers, cMax, pcTokens));
143
144 START_MD_PERF();
145 LOCKREAD();
146
147 if ( pEnum == 0 )
148 {
149 // instantiating a new ENUM
150 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
151
152 // create the enumerator
153 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtMethodDef, &pEnum) );
154
155 if ( IsGlobalMethodParentTk(cl) )
156 {
157 cl = m_tdModule;
158 }
159
160 // get the range of method rids given a typedef
161 IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(cl), &pRec));
162 ridStart = pMiniMd->getMethodListOfTypeDef(pRec);
163 IfFailGo(pMiniMd->getEndMethodListOfTypeDef(RidFromToken(cl), &ridEnd));
164
165 for (index = ridStart; index < ridEnd; index++ )
166 {
167 if (szNameUtf8 == NULL)
168 {
169 RID rid;
170 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
171 IfFailGo(HENUMInternal::AddElementToEnum(
172 pEnum,
173 TokenFromRid(rid, mdtMethodDef)));
174 }
175 else
176 {
177 RID rid;
178 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
179 IfFailGo(pMiniMd->GetMethodRecord(rid, &pMethod));
180 IfFailGo(pMiniMd->getNameOfMethod(pMethod, &szNameUtf8Tmp));
181 if ( strcmp(szNameUtf8Tmp, szNameUtf8) == 0 )
182 {
183 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
184 IfFailGo(HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(rid, mdtMethodDef)));
185 }
186 }
187 }
188
189 ridStart = m_pStgdb->m_MiniMd.getFieldListOfTypeDef(pRec);
190 IfFailGo(m_pStgdb->m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(cl), &ridEnd));
191
192 for (index = ridStart; index < ridEnd; index++ )
193 {
194 if (szNameUtf8 == NULL)
195 {
196 RID rid;
197 IfFailGo(pMiniMd->GetFieldRid(index, &rid));
198 IfFailGo(HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(rid, mdtFieldDef)));
199 }
200 else
201 {
202 RID rid;
203 IfFailGo(pMiniMd->GetFieldRid(index, &rid));
204 IfFailGo(pMiniMd->GetFieldRecord(rid, &pField));
205 IfFailGo(pMiniMd->getNameOfField(pField, &szNameUtf8Tmp));
206 if ( strcmp(szNameUtf8Tmp, szNameUtf8) == 0 )
207 {
208 IfFailGo(pMiniMd->GetFieldRid(index, &rid));
209 IfFailGo(HENUMInternal::AddElementToEnum(
210 pEnum,
211 TokenFromRid(rid, mdtFieldDef)));
212 }
213 }
214 }
215
216 // set the output parameter
217 *ppmdEnum = pEnum;
218 }
219
220 // fill the output token buffer
221 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rMembers, pcTokens);
222
223ErrExit:
224 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
225
226 STOP_MD_PERF(EnumMembersWithName);
227 END_ENTRYPOINT_NOTHROW;
228
229 return hr;
230} // STDMETHODIMP RegMeta::EnumMembersWithName()
231
232//*****************************************************************************
233// enumerating through methods given a Typedef and the flag
234//*****************************************************************************
235STDMETHODIMP RegMeta::EnumMethods(
236 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
237 mdTypeDef td, // [IN] TypeDef to scope the enumeration.
238 mdMethodDef rMethods[], // [OUT] Put MethodDefs here.
239 ULONG cMax, // [IN] Max MethodDefs to put.
240 ULONG *pcTokens) // [OUT] Put # put here.
241{
242 HRESULT hr = NOERROR;
243
244 BEGIN_ENTRYPOINT_NOTHROW;
245
246 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
247 ULONG ridStart;
248 ULONG ridEnd;
249 TypeDefRec *pRec;
250 HENUMInternal *pEnum = *ppmdEnum;
251
252 LOG((LOGMD, "MD RegMeta::EnumMethods(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
253 phEnum, td, rMethods, cMax, pcTokens));
254
255
256
257 START_MD_PERF();
258 LOCKREAD();
259
260 if ( pEnum == 0 )
261 {
262 // instantiating a new ENUM
263 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
264
265 // Check for mdTypeDefNil (representing <Module>).
266 // If so, this will map it to its token.
267 //
268 if ( IsGlobalMethodParentTk(td) )
269 {
270 td = m_tdModule;
271 }
272
273 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pRec));
274 ridStart = m_pStgdb->m_MiniMd.getMethodListOfTypeDef(pRec);
275 IfFailGo(m_pStgdb->m_MiniMd.getEndMethodListOfTypeDef(RidFromToken(td), &ridEnd));
276
277 if (pMiniMd->HasIndirectTable(TBL_Method) || pMiniMd->HasDelete())
278 {
279 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtMethodDef, &pEnum) );
280
281 // add all methods to the dynamic array
282 for (ULONG index = ridStart; index < ridEnd; index++ )
283 {
284 if (pMiniMd->HasDelete() &&
285 ((m_OptionValue.m_ImportOption & MDImportOptionAllMethodDefs) == 0))
286 {
287 MethodRec *pMethRec;
288 RID rid;
289 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
290 IfFailGo(pMiniMd->GetMethodRecord(rid, &pMethRec));
291 LPCSTR szMethodName;
292 IfFailGo(pMiniMd->getNameOfMethod(pMethRec, &szMethodName));
293 if (IsMdRTSpecialName(pMethRec->GetFlags()) && IsDeletedName(szMethodName) )
294 {
295 continue;
296 }
297 }
298 RID rid;
299 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
300 IfFailGo(HENUMInternal::AddElementToEnum(
301 pEnum,
302 TokenFromRid(rid, mdtMethodDef)));
303 }
304 }
305 else
306 {
307 IfFailGo( HENUMInternal::CreateSimpleEnum( mdtMethodDef, ridStart, ridEnd, &pEnum) );
308 }
309
310 // set the output parameter
311 *ppmdEnum = pEnum;
312 }
313
314 // fill the output token buffer
315 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rMethods, pcTokens);
316
317ErrExit:
318 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
319
320 STOP_MD_PERF(EnumMethods);
321 END_ENTRYPOINT_NOTHROW;
322
323 return hr;
324} // STDMETHODIMP RegMeta::EnumMethods()
325
326
327
328
329//*****************************************************************************
330// Enumerate over all the methods with szName in a TypeDef.
331//*****************************************************************************
332STDMETHODIMP RegMeta::EnumMethodsWithName( // S_OK, S_FALSE, or error.
333 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
334 mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
335 LPCWSTR szName, // [IN] Limit results to those with this name.
336 mdMethodDef rMethods[], // [OU] Put MethodDefs here.
337 ULONG cMax, // [IN] Max MethodDefs to put.
338 ULONG *pcTokens) // [OUT] Put # put here.
339{
340 HRESULT hr = NOERROR;
341
342 BEGIN_ENTRYPOINT_NOTHROW;
343
344 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
345 ULONG ridStart;
346 ULONG ridEnd;
347 ULONG index;
348 TypeDefRec *pRec;
349 MethodRec *pMethod;
350 HENUMInternal *pEnum = *ppmdEnum;
351 LPUTF8 szNameUtf8;
352 UTF8STR(szName, szNameUtf8);
353 LPCUTF8 szNameUtf8Tmp;
354
355 LOG((LOGMD, "MD RegMeta::EnumMethodsWithName(0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
356 phEnum, cl, MDSTR(szName), rMethods, cMax, pcTokens));
357
358
359
360 START_MD_PERF();
361 LOCKREAD();
362
363
364 if ( pEnum == 0 )
365 {
366 // instantiating a new ENUM
367 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
368
369 // Check for mdTypeDefNil (representing <Module>).
370 // If so, this will map it to its token.
371 //
372 if ( IsGlobalMethodParentTk(cl) )
373 {
374 cl = m_tdModule;
375 }
376
377
378 // create the enumerator
379 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtMethodDef, &pEnum) );
380
381 // get the range of method rids given a typedef
382 IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(cl), &pRec));
383 ridStart = pMiniMd->getMethodListOfTypeDef(pRec);
384 IfFailGo(pMiniMd->getEndMethodListOfTypeDef(RidFromToken(cl), &ridEnd));
385
386 for (index = ridStart; index < ridEnd; index++ )
387 {
388 if ( szNameUtf8 == NULL )
389 {
390 RID rid;
391 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
392 IfFailGo(HENUMInternal::AddElementToEnum(
393 pEnum,
394 TokenFromRid(rid, mdtMethodDef)));
395 }
396 else
397 {
398 RID rid;
399 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
400 IfFailGo(pMiniMd->GetMethodRecord(rid, &pMethod));
401 IfFailGo(pMiniMd->getNameOfMethod(pMethod, &szNameUtf8Tmp));
402 if ( strcmp(szNameUtf8Tmp, szNameUtf8) == 0 )
403 {
404 IfFailGo(pMiniMd->GetMethodRid(index, &rid));
405 IfFailGo(HENUMInternal::AddElementToEnum(
406 pEnum,
407 TokenFromRid(rid, mdtMethodDef)));
408 }
409 }
410 }
411
412 // set the output parameter
413 *ppmdEnum = pEnum;
414 }
415
416 // fill the output token buffer
417 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rMethods, pcTokens);
418
419ErrExit:
420 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
421
422 STOP_MD_PERF(EnumMethodsWithName);
423 END_ENTRYPOINT_NOTHROW;
424
425 return hr;
426} // STDMETHODIMP RegMeta::EnumMethodsWithName()
427
428
429
430//*****************************************************************************
431// Enumerate over all the fields in a TypeDef and a flag.
432//*****************************************************************************
433STDMETHODIMP
434RegMeta::EnumFields(
435 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
436 mdTypeDef td, // [IN] TypeDef to scope the enumeration.
437 mdFieldDef rFields[], // [OUT] Put FieldDefs here.
438 ULONG cMax, // [IN] Max FieldDefs to put.
439 ULONG *pcTokens) // [OUT] Put # put here.
440{
441 HRESULT hr = NOERROR;
442
443 BEGIN_ENTRYPOINT_NOTHROW;
444
445 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **>(phEnum);
446 ULONG ridStart;
447 ULONG ridEnd;
448 TypeDefRec *pRec;
449 HENUMInternal *pEnum = *ppmdEnum;
450
451 LOG((LOGMD, "MD RegMeta::EnumFields(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
452 phEnum, td, rFields, cMax, pcTokens));
453
454 START_MD_PERF();
455 LOCKREAD();
456
457 if (pEnum == NULL)
458 {
459 // instantiating a new ENUM
460 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
461
462 // Check for mdTypeDefNil (representing <Module>).
463 // If so, this will map it to its token.
464 //
465 if (IsGlobalMethodParentTk(td))
466 {
467 td = m_tdModule;
468 }
469
470 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pRec));
471 ridStart = m_pStgdb->m_MiniMd.getFieldListOfTypeDef(pRec);
472 IfFailGo(m_pStgdb->m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(td), &ridEnd));
473
474 if (pMiniMd->HasIndirectTable(TBL_Field) || pMiniMd->HasDelete())
475 {
476 IfFailGo(HENUMInternal::CreateDynamicArrayEnum(mdtFieldDef, &pEnum));
477
478 // add all methods to the dynamic array
479 for (ULONG index = ridStart; index < ridEnd; index++)
480 {
481 if (pMiniMd->HasDelete() &&
482 ((m_OptionValue.m_ImportOption & MDImportOptionAllFieldDefs) == 0))
483 {
484 FieldRec *pFieldRec;
485 RID rid;
486 IfFailGo(pMiniMd->GetFieldRid(index, &rid));
487 IfFailGo(pMiniMd->GetFieldRecord(rid, &pFieldRec));
488 LPCUTF8 szFieldName;
489 IfFailGo(pMiniMd->getNameOfField(pFieldRec, &szFieldName));
490 if (IsFdRTSpecialName(pFieldRec->GetFlags()) && IsDeletedName(szFieldName))
491 {
492 continue;
493 }
494 }
495 RID rid;
496 IfFailGo(pMiniMd->GetFieldRid(index, &rid));
497 IfFailGo(HENUMInternal::AddElementToEnum(
498 pEnum,
499 TokenFromRid(rid, mdtFieldDef)));
500 }
501 }
502 else
503 {
504 IfFailGo(HENUMInternal::CreateSimpleEnum(mdtFieldDef, ridStart, ridEnd, &pEnum));
505 }
506
507 // set the output parameter
508 *ppmdEnum = pEnum;
509 }
510
511 // fill the output token buffer
512 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rFields, pcTokens);
513
514ErrExit:
515 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
516
517 STOP_MD_PERF(EnumFields);
518 END_ENTRYPOINT_NOTHROW;
519
520 return hr;
521} // RegMeta::EnumFields
522
523
524
525//*****************************************************************************
526// Enumerate over all the fields with szName in a TypeDef.
527//*****************************************************************************
528STDMETHODIMP RegMeta::EnumFieldsWithName( // S_OK, S_FALSE, or error.
529 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
530 mdTypeDef cl, // [IN] TypeDef to scope the enumeration.
531 LPCWSTR szName, // [IN] Limit results to those with this name.
532 mdFieldDef rFields[], // [OUT] Put MemberDefs here.
533 ULONG cMax, // [IN] Max MemberDefs to put.
534 ULONG *pcTokens) // [OUT] Put # put here.
535{
536 HRESULT hr = NOERROR;
537
538 BEGIN_ENTRYPOINT_NOTHROW;
539
540 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
541 ULONG ridStart;
542 ULONG ridEnd;
543 ULONG index;
544 TypeDefRec *pRec;
545 FieldRec *pField;
546 HENUMInternal *pEnum = *ppmdEnum;
547 LPUTF8 szNameUtf8;
548 UTF8STR(szName, szNameUtf8);
549 LPCUTF8 szNameUtf8Tmp;
550
551 LOG((LOGMD, "MD RegMeta::EnumFields(0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
552 phEnum, cl, MDSTR(szName), rFields, cMax, pcTokens));
553
554
555
556 START_MD_PERF();
557 LOCKREAD();
558
559 if ( pEnum == 0 )
560 {
561 // instantiating a new ENUM
562 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
563
564 // Check for mdTypeDefNil (representing <Module>).
565 // If so, this will map it to its token.
566 //
567 if ( IsGlobalMethodParentTk(cl) )
568 {
569 cl = m_tdModule;
570 }
571
572 // create the enumerator
573 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtMethodDef, &pEnum) );
574
575 // get the range of field rids given a typedef
576 IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(cl), &pRec));
577 ridStart = m_pStgdb->m_MiniMd.getFieldListOfTypeDef(pRec);
578 IfFailGo(m_pStgdb->m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(cl), &ridEnd));
579
580 for (index = ridStart; index < ridEnd; index++ )
581 {
582 if ( szNameUtf8 == NULL )
583 {
584 RID rid;
585 IfFailGo(pMiniMd->GetFieldRid(index, &rid));
586 IfFailGo(HENUMInternal::AddElementToEnum(
587 pEnum,
588 TokenFromRid(rid, mdtFieldDef)));
589 }
590 else
591 {
592 RID rid;
593 IfFailGo(pMiniMd->GetFieldRid(index, &rid));
594 IfFailGo(pMiniMd->GetFieldRecord(rid, &pField));
595 IfFailGo(pMiniMd->getNameOfField(pField, &szNameUtf8Tmp));
596 if ( strcmp(szNameUtf8Tmp, szNameUtf8) == 0 )
597 {
598 IfFailGo(pMiniMd->GetFieldRid(index, &rid));
599 IfFailGo( HENUMInternal::AddElementToEnum(
600 pEnum,
601 TokenFromRid(rid, mdtFieldDef) ) );
602 }
603 }
604 }
605
606 // set the output parameter
607 *ppmdEnum = pEnum;
608 }
609
610 // fill the output token buffer
611 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rFields, pcTokens);
612
613ErrExit:
614 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
615
616 STOP_MD_PERF(EnumFieldsWithName);
617 END_ENTRYPOINT_NOTHROW;
618
619 return hr;
620} // STDMETHODIMP RegMeta::EnumFieldsWithName()
621
622
623//*****************************************************************************
624// Enumerate over the ParamDefs in a Method.
625//*****************************************************************************
626STDMETHODIMP RegMeta::EnumParams( // S_OK, S_FALSE, or error.
627 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
628 mdMethodDef mb, // [IN] MethodDef to scope the enumeration.
629 mdParamDef rParams[], // [OUT] Put ParamDefs here.
630 ULONG cMax, // [IN] Max ParamDefs to put.
631 ULONG *pcTokens) // [OUT] Put # put here.
632{
633 HRESULT hr = NOERROR;
634
635 BEGIN_ENTRYPOINT_NOTHROW;
636
637 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
638 ULONG ridStart;
639 ULONG ridEnd;
640 MethodRec *pRec;
641 HENUMInternal *pEnum = *ppmdEnum;
642
643 LOG((LOGMD, "MD RegMeta::EnumParams(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
644 phEnum, mb, rParams, cMax, pcTokens));
645 START_MD_PERF();
646 LOCKREAD();
647
648
649 if ( pEnum == 0 )
650 {
651 // instantiating a new ENUM
652 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
653 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(mb), &pRec));
654 ridStart = m_pStgdb->m_MiniMd.getParamListOfMethod(pRec);
655 IfFailGo(m_pStgdb->m_MiniMd.getEndParamListOfMethod(RidFromToken(mb), &ridEnd));
656
657 if (pMiniMd->HasIndirectTable(TBL_Param))
658 {
659 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtParamDef, &pEnum) );
660
661 // add all methods to the dynamic array
662 for (ULONG index = ridStart; index < ridEnd; index++ )
663 {
664 RID rid;
665 IfFailGo(pMiniMd->GetParamRid(index, &rid));
666 IfFailGo(HENUMInternal::AddElementToEnum(
667 pEnum,
668 TokenFromRid(rid, mdtParamDef)));
669 }
670 }
671 else
672 {
673 IfFailGo( HENUMInternal::CreateSimpleEnum( mdtParamDef, ridStart, ridEnd, &pEnum) );
674 }
675
676 // set the output parameter
677 *ppmdEnum = pEnum;
678 }
679
680 // fill the output token buffer
681 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rParams, pcTokens);
682
683ErrExit:
684 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
685
686 STOP_MD_PERF(EnumParams);
687 END_ENTRYPOINT_NOTHROW;
688
689 return hr;
690} // STDMETHODIMP RegMeta::EnumParams()
691
692
693
694//*****************************************************************************
695// Enumerate the MemberRefs given the parent token.
696//*****************************************************************************
697STDMETHODIMP RegMeta::EnumMemberRefs( // S_OK, S_FALSE, or error.
698 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
699 mdToken tkParent, // [IN] Parent token to scope the enumeration.
700 mdMemberRef rMemberRefs[], // [OUT] Put MemberRefs here.
701 ULONG cMax, // [IN] Max MemberRefs to put.
702 ULONG *pcTokens) // [OUT] Put # put here.
703{
704 HRESULT hr = NOERROR;
705
706 BEGIN_ENTRYPOINT_NOTHROW;
707
708 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
709 ULONG ridEnd;
710 ULONG index;
711 MemberRefRec *pRec;
712 HENUMInternal *pEnum = *ppmdEnum;
713
714 LOG((LOGMD, "MD RegMeta::EnumMemberRefs(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
715 phEnum, tkParent, rMemberRefs, cMax, pcTokens));
716
717
718
719 START_MD_PERF();
720 LOCKREAD();
721
722 if ( pEnum == 0 )
723 {
724 // instantiating a new ENUM
725 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
726 mdToken tk;
727
728 // Check for mdTypeDefNil (representing <Module>).
729 // If so, this will map it to its token.
730 //
731 IsGlobalMethodParent(&tkParent);
732
733 // create the enumerator
734 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtMemberRef, &pEnum) );
735
736 // get the range of field rids given a typedef
737 ridEnd = pMiniMd->getCountMemberRefs();
738
739 for (index = 1; index <= ridEnd; index++ )
740 {
741 IfFailGo(pMiniMd->GetMemberRefRecord(index, &pRec));
742 tk = pMiniMd->getClassOfMemberRef(pRec);
743 if ( tk == tkParent )
744 {
745 // add the matched ones to the enumerator
746 IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtMemberRef) ) );
747 }
748 }
749
750 // set the output parameter
751 *ppmdEnum = pEnum;
752 }
753
754 // fill the output token buffer
755 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rMemberRefs, pcTokens);
756
757ErrExit:
758 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
759
760 STOP_MD_PERF(EnumMemberRefs);
761
762 END_ENTRYPOINT_NOTHROW;
763
764 return hr;
765} // STDMETHODIMP RegMeta::EnumMemberRefs()
766
767
768//*****************************************************************************
769// Enumerate methodimpls given a typedef
770//*****************************************************************************
771STDMETHODIMP RegMeta::EnumMethodImpls( // S_OK, S_FALSE, or error
772 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
773 mdTypeDef td, // [IN] TypeDef to scope the enumeration.
774 mdToken rMethodBody[], // [OUT] Put Method Body tokens here.
775 mdToken rMethodDecl[], // [OUT] Put Method Declaration tokens here.
776 ULONG cMax, // [IN] Max tokens to put.
777 ULONG *pcTokens) // [OUT] Put # put here.
778{
779 HRESULT hr = NOERROR;
780
781 BEGIN_ENTRYPOINT_NOTHROW;
782
783 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
784 MethodImplRec *pRec;
785 HENUMInternal *pEnum = *ppmdEnum;
786 HENUMInternal hEnum;
787
788
789 LOG((LOGMD, "MD RegMeta::EnumMethodImpls(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
790 phEnum, td, rMethodBody, rMethodDecl, cMax, pcTokens));
791
792
793
794 START_MD_PERF();
795 LOCKREAD();
796
797 memset(&hEnum, 0, sizeof(HENUMInternal));
798
799 if ( pEnum == 0 )
800 {
801 // instantiating a new ENUM
802 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
803 mdToken tkMethodBody;
804 mdToken tkMethodDecl;
805 RID ridCur;
806
807 // Get the range of rids.
808 IfFailGo( pMiniMd->FindMethodImplHelper(td, &hEnum) );
809
810 // Create the enumerator, DynamicArrayEnum does not use the token type.
811 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( (TBL_MethodImpl << 24), &pEnum) );
812
813 while (HENUMInternal::EnumNext(&hEnum, (mdToken *)&ridCur))
814 {
815 // Get the MethodBody and MethodDeclaration tokens for the current
816 // MethodImpl record.
817 IfFailGo(pMiniMd->GetMethodImplRecord(ridCur, &pRec));
818 tkMethodBody = pMiniMd->getMethodBodyOfMethodImpl(pRec);
819 tkMethodDecl = pMiniMd->getMethodDeclarationOfMethodImpl(pRec);
820
821 // Add the Method body/declaration pairs to the Enum
822 IfFailGo( HENUMInternal::AddElementToEnum(pEnum, tkMethodBody ) );
823 IfFailGo( HENUMInternal::AddElementToEnum(pEnum, tkMethodDecl ) );
824 }
825
826 // set the output parameter
827 *ppmdEnum = pEnum;
828 }
829
830 // fill the output token buffer
831 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rMethodBody, rMethodDecl, pcTokens);
832
833ErrExit:
834 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
835 HENUMInternal::ClearEnum(&hEnum);
836
837 STOP_MD_PERF(EnumMethodImpls);
838 END_ENTRYPOINT_NOTHROW;
839
840 return hr;
841} // STDMETHODIMP RegMeta::EnumMethodImpls()
842
843
844//*****************************************************************************
845// Enumerate over PermissionSets. Optionally limit to an object and/or an
846// action.
847//*****************************************************************************
848STDMETHODIMP RegMeta::EnumPermissionSets( // S_OK, S_FALSE, or error.
849 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
850 mdToken tk, // [IN] if !NIL, token to scope the enumeration.
851 DWORD dwActions, // [IN] if !0, return only these actions.
852 mdPermission rPermission[], // [OUT] Put Permissions here.
853 ULONG cMax, // [IN] Max Permissions to put.
854 ULONG *pcTokens) // [OUT] Put # put here.
855{
856 HRESULT hr = NOERROR;
857
858 BEGIN_ENTRYPOINT_NOTHROW;
859
860 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
861 ULONG ridStart;
862 ULONG ridEnd;
863 ULONG index;
864 DeclSecurityRec *pRec;
865 HENUMInternal *pEnum = *ppmdEnum;
866 bool fCompareParent = false;
867 mdToken typ = TypeFromToken(tk);
868 mdToken tkParent;
869
870 LOG((LOGMD, "MD RegMeta::EnumPermissionSets(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
871 phEnum, tk, dwActions, rPermission, cMax, pcTokens));
872
873 START_MD_PERF();
874 LOCKREAD();
875
876 if ( pEnum == 0 )
877 {
878 // Does this token type even have security?
879 if (tk != 0 &&
880 !(typ == mdtTypeDef || typ == mdtMethodDef || typ == mdtAssembly))
881 {
882 if (pcTokens)
883 *pcTokens = 0;
884 hr = S_FALSE;
885 goto ErrExit;
886 }
887
888 // instantiating a new ENUM
889 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
890
891 if (!IsNilToken(tk))
892 {
893 // parent is provided for lookup
894 if ( pMiniMd->IsSorted( TBL_DeclSecurity ) )
895 {
896 IfFailGo(pMiniMd->getDeclSecurityForToken(tk, &ridEnd, &ridStart));
897 }
898 else
899 {
900 // table is not sorted. So we have to do a table scan
901 ridStart = 1;
902 ridEnd = pMiniMd->getCountDeclSecuritys() + 1;
903 fCompareParent = true;
904 }
905 }
906 else
907 {
908 ridStart = 1;
909 ridEnd = pMiniMd->getCountDeclSecuritys() + 1;
910 }
911
912 if (IsDclActionNil(dwActions) && !fCompareParent && !m_pStgdb->m_MiniMd.HasDelete())
913 {
914 // create simple enumerator
915 IfFailGo( HENUMInternal::CreateSimpleEnum( mdtPermission, ridStart, ridEnd, &pEnum) );
916 }
917 else
918 {
919 // create the dynamic enumerator
920 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtPermission, &pEnum) );
921
922 for (index = ridStart; index < ridEnd; index++ )
923 {
924 IfFailGo(pMiniMd->GetDeclSecurityRecord(index, &pRec));
925 tkParent = pMiniMd->getParentOfDeclSecurity(pRec);
926 if ( (fCompareParent && tk != tkParent) ||
927 IsNilToken(tkParent) )
928 {
929 // We need to compare parent token and they are not equal so skip
930 // over this row.
931 //
932 continue;
933 }
934 if ( IsDclActionNil(dwActions) ||
935 ( (DWORD)(pMiniMd->getActionOfDeclSecurity(pRec))) == dwActions )
936 {
937 // If we don't need to compare the action, just add to the enum.
938 // Or we need to compare the action and the action values are equal, add to enum as well.
939 //
940 IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtPermission) ) );
941 }
942 }
943 }
944
945 // set the output parameter
946 *ppmdEnum = pEnum;
947 }
948
949 // fill the output token buffer
950 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rPermission, pcTokens);
951
952ErrExit:
953 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
954
955 STOP_MD_PERF(EnumPermissionSets);
956 END_ENTRYPOINT_NOTHROW;
957
958 return hr;
959} // STDMETHODIMP RegMeta::EnumPermissionSets()
960
961
962//*****************************************************************************
963// Find a given member in a TypeDef (typically a class).
964//*****************************************************************************
965STDMETHODIMP RegMeta::FindMember(
966 mdTypeDef td, // [IN] given typedef
967 LPCWSTR szName, // [IN] member name
968 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
969 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
970 mdToken *pmb) // [OUT] matching memberdef
971{
972 HRESULT hr = NOERROR;
973
974 BEGIN_ENTRYPOINT_NOTHROW;
975
976
977 LOG((LOGMD, "MD RegMeta::FindMember(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
978 td, MDSTR(szName), pvSigBlob, cbSigBlob, pmb));
979
980 START_MD_PERF();
981
982 // Don't lock this function. All of the functions that it calls are public APIs. keep it that way.
983
984 // try to match with method first of all
985 hr = FindMethod(
986 td,
987 szName,
988 pvSigBlob,
989 cbSigBlob,
990 pmb);
991
992 if ( hr == CLDB_E_RECORD_NOTFOUND )
993 {
994 // now try field table
995 IfFailGo( FindField(
996 td,
997 szName,
998 pvSigBlob,
999 cbSigBlob,
1000 pmb) );
1001 }
1002ErrExit:
1003 STOP_MD_PERF(FindMember);
1004 END_ENTRYPOINT_NOTHROW;
1005
1006 return hr;
1007} // STDMETHODIMP RegMeta::FindMember()
1008
1009
1010
1011//*****************************************************************************
1012// Find a given member in a TypeDef (typically a class).
1013//*****************************************************************************
1014STDMETHODIMP RegMeta::FindMethod(
1015 mdTypeDef td, // [IN] given typedef
1016 LPCWSTR szName, // [IN] member name
1017 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
1018 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
1019 mdMethodDef *pmb) // [OUT] matching memberdef
1020{
1021 HRESULT hr = NOERROR;
1022
1023 BEGIN_ENTRYPOINT_NOTHROW;
1024
1025 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1026 LPUTF8 szNameUtf8;
1027 UTF8STR(szName, szNameUtf8);
1028
1029 LOG((LOGMD, "MD RegMeta::FindMethod(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
1030 td, MDSTR(szName), pvSigBlob, cbSigBlob, pmb));
1031
1032 START_MD_PERF();
1033 LOCKREAD();
1034
1035 if (szName == NULL)
1036 IfFailGo(E_INVALIDARG);
1037 PREFIX_ASSUME(szName != NULL);
1038
1039 // If this is a global method, then use the <Module> typedef as parent.
1040 IsGlobalMethodParent(&td);
1041
1042 IfFailGo(ImportHelper::FindMethod(pMiniMd,
1043 td,
1044 szNameUtf8,
1045 pvSigBlob,
1046 cbSigBlob,
1047 pmb));
1048
1049ErrExit:
1050 STOP_MD_PERF(FindMethod);
1051 END_ENTRYPOINT_NOTHROW;
1052
1053 return hr;
1054} // RegMeta::FindMethod
1055
1056
1057//*****************************************************************************
1058// Find a given member in a TypeDef (typically a class).
1059//*****************************************************************************
1060STDMETHODIMP
1061RegMeta::FindField(
1062 mdTypeDef td, // [IN] given typedef
1063 LPCWSTR szName, // [IN] member name
1064 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
1065 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
1066 mdFieldDef *pmb) // [OUT] matching memberdef
1067{
1068 HRESULT hr = NOERROR;
1069
1070 BEGIN_ENTRYPOINT_NOTHROW;
1071
1072 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1073
1074 LOG((LOGMD, "MD RegMeta::FindField(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
1075 td, MDSTR(szName), pvSigBlob, cbSigBlob, pmb));
1076
1077 START_MD_PERF();
1078 LOCKREAD();
1079
1080 if (szName == NULL)
1081 IfFailGo(E_INVALIDARG);
1082
1083 LPUTF8 szNameUtf8;
1084 UTF8STR(szName, szNameUtf8);
1085
1086 // If this is a global method, then use the <Module> typedef as parent.
1087 IsGlobalMethodParent(&td);
1088
1089 IfFailGo(ImportHelper::FindField(pMiniMd,
1090 td,
1091 szNameUtf8,
1092 pvSigBlob,
1093 cbSigBlob,
1094 pmb));
1095
1096ErrExit:
1097 STOP_MD_PERF(FindField);
1098 END_ENTRYPOINT_NOTHROW;
1099
1100 return hr;
1101} // RegMeta::FindField
1102
1103
1104//*****************************************************************************
1105// Find a given MemberRef in a TypeRef (typically a class). If no TypeRef
1106// is specified, the query will be for a random member in the scope.
1107//*****************************************************************************
1108STDMETHODIMP RegMeta::FindMemberRef(
1109 mdToken tkPar, // [IN] given parent token.
1110 LPCWSTR szName, // [IN] member name
1111 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
1112 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
1113 mdMemberRef *pmr) // [OUT] matching memberref
1114{
1115 HRESULT hr = NOERROR;
1116
1117 BEGIN_ENTRYPOINT_NOTHROW;
1118
1119 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1120 LPUTF8 szNameUtf8;
1121 UTF8STR(szName, szNameUtf8);
1122
1123 LOG((LOGMD, "MD RegMeta::FindMemberRef(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
1124 tkPar, MDSTR(szName), pvSigBlob, cbSigBlob, pmr));
1125
1126
1127
1128 START_MD_PERF();
1129
1130 // <TODO>@todo: Can this causing building hash table? If so, should this consider the write lock?</TODO>
1131 LOCKREAD();
1132
1133 // get the range of field rids given a typedef
1134 _ASSERTE(TypeFromToken(tkPar) == mdtTypeRef || TypeFromToken(tkPar) == mdtMethodDef ||
1135 TypeFromToken(tkPar) == mdtModuleRef || TypeFromToken(tkPar) == mdtTypeDef ||
1136 TypeFromToken(tkPar) == mdtTypeSpec);
1137
1138 // Set parent to global class m_tdModule if mdTokenNil is passed.
1139 if (IsNilToken(tkPar))
1140 tkPar = m_tdModule;
1141
1142 IfFailGo( ImportHelper::FindMemberRef(pMiniMd, tkPar, szNameUtf8, pvSigBlob, cbSigBlob, pmr) );
1143
1144ErrExit:
1145
1146 STOP_MD_PERF(FindMemberRef);
1147 END_ENTRYPOINT_NOTHROW;
1148
1149 return hr;
1150} // STDMETHODIMP RegMeta::FindMemberRef()
1151
1152
1153//*****************************************************************************
1154// Return the property of a MethodDef
1155//*****************************************************************************
1156STDMETHODIMP RegMeta::GetMethodProps(
1157 mdMethodDef mb, // The method for which to get props.
1158 mdTypeDef *pClass, // Put method's class here.
1159 __out_ecount_opt (cchMethod) LPWSTR szMethod, // Put method's name here.
1160 ULONG cchMethod, // Size of szMethod buffer in wide chars.
1161 ULONG *pchMethod, // Put actual size here
1162 DWORD *pdwAttr, // Put flags here.
1163 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
1164 ULONG *pcbSigBlob, // [OUT] actual size of signature blob
1165 ULONG *pulCodeRVA, // [OUT] codeRVA
1166 DWORD *pdwImplFlags) // [OUT] Impl. Flags
1167{
1168 HRESULT hr = NOERROR;
1169 BEGIN_ENTRYPOINT_NOTHROW;
1170
1171 MethodRec *pMethodRec;
1172 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1173
1174 LOG((LOGMD, "MD RegMeta::GetMethodProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1175 mb, pClass, szMethod, cchMethod, pchMethod, pdwAttr, ppvSigBlob, pcbSigBlob,
1176 pulCodeRVA, pdwImplFlags));
1177
1178
1179
1180 START_MD_PERF();
1181 LOCKREAD();
1182
1183 _ASSERTE(TypeFromToken(mb) == mdtMethodDef);
1184
1185 IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(mb), &pMethodRec));
1186
1187 if (pClass)
1188 {
1189 // caller wants parent typedef
1190 IfFailGo( pMiniMd->FindParentOfMethodHelper(mb, pClass) );
1191
1192 if ( IsGlobalMethodParentToken(*pClass) )
1193 {
1194 // If the parent of Method is the <Module>, return mdTypeDefNil instead.
1195 *pClass = mdTypeDefNil;
1196 }
1197
1198 }
1199 if (ppvSigBlob || pcbSigBlob)
1200 {
1201 // caller wants signature information
1202 PCCOR_SIGNATURE pvSigTmp;
1203 ULONG cbSig;
1204 IfFailGo(pMiniMd->getSignatureOfMethod(pMethodRec, &pvSigTmp, &cbSig));
1205 if ( ppvSigBlob )
1206 *ppvSigBlob = pvSigTmp;
1207 if ( pcbSigBlob)
1208 *pcbSigBlob = cbSig;
1209 }
1210 if ( pdwAttr )
1211 {
1212 *pdwAttr = pMiniMd->getFlagsOfMethod(pMethodRec);
1213 }
1214 if ( pulCodeRVA )
1215 {
1216 *pulCodeRVA = pMiniMd->getRVAOfMethod(pMethodRec);
1217 }
1218 if ( pdwImplFlags )
1219 {
1220 *pdwImplFlags = (DWORD )pMiniMd->getImplFlagsOfMethod(pMethodRec);
1221 }
1222 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
1223 if (szMethod || pchMethod)
1224 {
1225 IfFailGo( pMiniMd->getNameOfMethod(pMethodRec, szMethod, cchMethod, pchMethod) );
1226 }
1227
1228ErrExit:
1229 STOP_MD_PERF(GetMethodProps);
1230 END_ENTRYPOINT_NOTHROW;
1231
1232 return hr;
1233} // STDMETHODIMP RegMeta::GetMethodProps()
1234
1235
1236//*****************************************************************************
1237// Return the property of a MemberRef
1238//*****************************************************************************
1239STDMETHODIMP RegMeta::GetMemberRefProps( // S_OK or error.
1240 mdMemberRef mr, // [IN] given memberref
1241 mdToken *ptk, // [OUT] Put classref or classdef here.
1242 __out_ecount_opt (cchMember) LPWSTR szMember, // [OUT] buffer to fill for member's name
1243 ULONG cchMember, // [IN] the count of char of szMember
1244 ULONG *pchMember, // [OUT] actual count of char in member name
1245 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to meta data blob value
1246 ULONG *pbSig) // [OUT] actual size of signature blob
1247{
1248 HRESULT hr = NOERROR;
1249
1250 BEGIN_ENTRYPOINT_NOTHROW;
1251
1252 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1253 MemberRefRec *pMemberRefRec;
1254
1255 LOG((LOGMD, "MD RegMeta::GetMemberRefProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1256 mr, ptk, szMember, cchMember, pchMember, ppvSigBlob, pbSig));
1257
1258
1259
1260 START_MD_PERF();
1261 LOCKREAD();
1262
1263 _ASSERTE(TypeFromToken(mr) == mdtMemberRef);
1264
1265 IfFailGo(pMiniMd->GetMemberRefRecord(RidFromToken(mr), &pMemberRefRec));
1266
1267 if (ptk)
1268 {
1269 *ptk = pMiniMd->getClassOfMemberRef(pMemberRefRec);
1270 if ( IsGlobalMethodParentToken(*ptk) )
1271 {
1272 // If the parent of MemberRef is the <Module>, return mdTypeDefNil instead.
1273 *ptk = mdTypeDefNil;
1274 }
1275
1276 }
1277 if (ppvSigBlob || pbSig)
1278 {
1279 // caller wants signature information
1280 PCCOR_SIGNATURE pvSigTmp;
1281 ULONG cbSig;
1282 IfFailGo(pMiniMd->getSignatureOfMemberRef(pMemberRefRec, &pvSigTmp, &cbSig));
1283 if ( ppvSigBlob )
1284 *ppvSigBlob = pvSigTmp;
1285 if ( pbSig)
1286 *pbSig = cbSig;
1287 }
1288 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
1289 if (szMember || pchMember)
1290 {
1291 IfFailGo( pMiniMd->getNameOfMemberRef(pMemberRefRec, szMember, cchMember, pchMember) );
1292 }
1293
1294ErrExit:
1295
1296 STOP_MD_PERF(GetMemberRefProps);
1297 END_ENTRYPOINT_NOTHROW;
1298
1299 return hr;
1300} // STDMETHODIMP RegMeta::GetMemberRefProps()
1301
1302
1303//*****************************************************************************
1304// enumerate Property tokens for a typedef
1305//*****************************************************************************
1306STDMETHODIMP RegMeta::EnumProperties( // S_OK, S_FALSE, or error.
1307 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
1308 mdTypeDef td, // [IN] TypeDef to scope the enumeration.
1309 mdProperty rProperties[], // [OUT] Put Properties here.
1310 ULONG cMax, // [IN] Max properties to put.
1311 ULONG *pcProperties) // [OUT] Put # put here.
1312{
1313 HRESULT hr = NOERROR;
1314
1315 BEGIN_ENTRYPOINT_NOTHROW;
1316
1317 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
1318 ULONG ridStart = 0;
1319 ULONG ridEnd = 0;
1320 ULONG ridMax = 0;
1321 HENUMInternal *pEnum = *ppmdEnum;
1322
1323 LOG((LOGMD, "MD RegMeta::EnumProperties(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1324 phEnum, td, rProperties, cMax, pcProperties));
1325
1326 START_MD_PERF();
1327 LOCKREAD();
1328
1329 if (IsNilToken(td))
1330 {
1331 if (pcProperties)
1332 *pcProperties = 0;
1333 hr = S_FALSE;
1334 goto ErrExit;
1335 }
1336
1337 _ASSERTE(TypeFromToken(td) == mdtTypeDef);
1338
1339
1340 if ( pEnum == 0 )
1341 {
1342 // instantiating a new ENUM
1343 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1344 RID ridPropertyMap;
1345 PropertyMapRec *pPropertyMapRec;
1346
1347 // get the starting/ending rid of properties of this typedef
1348 IfFailGo(pMiniMd->FindPropertyMapFor(RidFromToken(td), &ridPropertyMap));
1349 if (!InvalidRid(ridPropertyMap))
1350 {
1351 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyMapRecord(ridPropertyMap, &pPropertyMapRec));
1352 ridStart = pMiniMd->getPropertyListOfPropertyMap(pPropertyMapRec);
1353 IfFailGo(pMiniMd->getEndPropertyListOfPropertyMap(ridPropertyMap, &ridEnd));
1354 ridMax = pMiniMd->getCountPropertys() + 1;
1355 if(ridStart == 0) ridStart = 1;
1356 if(ridEnd > ridMax) ridEnd = ridMax;
1357 if(ridStart > ridEnd) ridStart=ridEnd;
1358 }
1359
1360 if (pMiniMd->HasIndirectTable(TBL_Property) || pMiniMd->HasDelete())
1361 {
1362 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtProperty, &pEnum) );
1363
1364 // add all methods to the dynamic array
1365 for (ULONG index = ridStart; index < ridEnd; index++ )
1366 {
1367 if (pMiniMd->HasDelete() &&
1368 ((m_OptionValue.m_ImportOption & MDImportOptionAllProperties) == 0))
1369 {
1370 PropertyRec *pRec;
1371 RID rid;
1372 IfFailGo(pMiniMd->GetPropertyRid(index, &rid));
1373 IfFailGo(pMiniMd->GetPropertyRecord(rid, &pRec));
1374 LPCUTF8 szPropertyName;
1375 IfFailGo(pMiniMd->getNameOfProperty(pRec, &szPropertyName));
1376 if (IsPrRTSpecialName(pRec->GetPropFlags()) && IsDeletedName(szPropertyName))
1377 {
1378 continue;
1379 }
1380 }
1381 RID rid;
1382 IfFailGo(pMiniMd->GetPropertyRid(index, &rid));
1383 IfFailGo(HENUMInternal::AddElementToEnum(
1384 pEnum,
1385 TokenFromRid(rid, mdtProperty)));
1386 }
1387 }
1388 else
1389 {
1390 IfFailGo( HENUMInternal::CreateSimpleEnum( mdtProperty, ridStart, ridEnd, &pEnum) );
1391 }
1392
1393 // set the output parameter
1394 *ppmdEnum = pEnum;
1395 }
1396
1397 // fill the output token buffer
1398 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rProperties, pcProperties);
1399
1400ErrExit:
1401 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
1402
1403
1404 STOP_MD_PERF(EnumProperties);
1405 END_ENTRYPOINT_NOTHROW;
1406
1407 return hr;
1408
1409} // STDMETHODIMP RegMeta::EnumProperties()
1410
1411
1412//*****************************************************************************
1413// enumerate event tokens for a typedef
1414//*****************************************************************************
1415STDMETHODIMP RegMeta::EnumEvents( // S_OK, S_FALSE, or error.
1416 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
1417 mdTypeDef td, // [IN] TypeDef to scope the enumeration.
1418 mdEvent rEvents[], // [OUT] Put events here.
1419 ULONG cMax, // [IN] Max events to put.
1420 ULONG *pcEvents) // [OUT] Put # put here.
1421{
1422 HRESULT hr = NOERROR;
1423
1424 BEGIN_ENTRYPOINT_NOTHROW;
1425
1426 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
1427 ULONG ridStart = 0;
1428 ULONG ridEnd = 0;
1429 ULONG ridMax = 0;
1430 HENUMInternal *pEnum = *ppmdEnum;
1431
1432 LOG((LOGMD, "MD RegMeta::EnumEvents(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1433 phEnum, td, rEvents, cMax, pcEvents));
1434
1435 START_MD_PERF();
1436 LOCKREAD();
1437
1438 _ASSERTE(TypeFromToken(td) == mdtTypeDef);
1439
1440
1441 if ( pEnum == 0 )
1442 {
1443 // instantiating a new ENUM
1444 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1445 RID ridEventMap;
1446 EventMapRec *pEventMapRec;
1447
1448 // get the starting/ending rid of properties of this typedef
1449 IfFailGo(pMiniMd->FindEventMapFor(RidFromToken(td), &ridEventMap));
1450 if (!InvalidRid(ridEventMap))
1451 {
1452 IfFailGo(pMiniMd->GetEventMapRecord(ridEventMap, &pEventMapRec));
1453 ridStart = pMiniMd->getEventListOfEventMap(pEventMapRec);
1454 IfFailGo(pMiniMd->getEndEventListOfEventMap(ridEventMap, &ridEnd));
1455 ridMax = pMiniMd->getCountEvents() + 1;
1456 if(ridStart == 0) ridStart = 1;
1457 if(ridEnd > ridMax) ridEnd = ridMax;
1458 if(ridStart > ridEnd) ridStart=ridEnd;
1459 }
1460
1461 if (pMiniMd->HasIndirectTable(TBL_Event) || pMiniMd->HasDelete())
1462 {
1463 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtEvent, &pEnum) );
1464
1465 // add all methods to the dynamic array
1466 for (ULONG index = ridStart; index < ridEnd; index++ )
1467 {
1468 if (pMiniMd->HasDelete() &&
1469 ((m_OptionValue.m_ImportOption & MDImportOptionAllEvents) == 0))
1470 {
1471 EventRec *pRec;
1472 RID rid;
1473 IfFailGo(pMiniMd->GetEventRid(index, &rid));
1474 IfFailGo(pMiniMd->GetEventRecord(rid, &pRec));
1475 LPCSTR szEventName;
1476 IfFailGo(pMiniMd->getNameOfEvent(pRec, &szEventName));
1477 if (IsEvRTSpecialName(pRec->GetEventFlags()) && IsDeletedName(szEventName))
1478 {
1479 continue;
1480 }
1481 }
1482 RID rid;
1483 IfFailGo(pMiniMd->GetEventRid(index, &rid));
1484 IfFailGo(HENUMInternal::AddElementToEnum(
1485 pEnum,
1486 TokenFromRid(rid, mdtEvent)));
1487 }
1488 }
1489 else
1490 {
1491 IfFailGo( HENUMInternal::CreateSimpleEnum( mdtEvent, ridStart, ridEnd, &pEnum) );
1492 }
1493
1494 // set the output parameter
1495 *ppmdEnum = pEnum;
1496 }
1497
1498 // fill the output token buffer
1499 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rEvents, pcEvents);
1500
1501ErrExit:
1502 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
1503
1504
1505 STOP_MD_PERF(EnumEvents);
1506 END_ENTRYPOINT_NOTHROW;
1507
1508 return hr;
1509} // STDMETHODIMP RegMeta::EnumEvents()
1510
1511
1512
1513//*****************************************************************************
1514// return the properties of an event token
1515//*****************************************************************************
1516STDMETHODIMP RegMeta::GetEventProps( // S_OK, S_FALSE, or error.
1517 mdEvent ev, // [IN] event token
1518 mdTypeDef *pClass, // [OUT] typedef containing the event declarion.
1519 LPCWSTR szEvent, // [OUT] Event name
1520 ULONG cchEvent, // [IN] the count of wchar of szEvent
1521 ULONG *pchEvent, // [OUT] actual count of wchar for event's name
1522 DWORD *pdwEventFlags, // [OUT] Event flags.
1523 mdToken *ptkEventType, // [OUT] EventType class
1524 mdMethodDef *pmdAddOn, // [OUT] AddOn method of the event
1525 mdMethodDef *pmdRemoveOn, // [OUT] RemoveOn method of the event
1526 mdMethodDef *pmdFire, // [OUT] Fire method of the event
1527 mdMethodDef rmdOtherMethod[], // [OUT] other method of the event
1528 ULONG cMax, // [IN] size of rmdOtherMethod
1529 ULONG *pcOtherMethod) // [OUT] total number of other method of this event
1530{
1531 HRESULT hr = NOERROR;
1532
1533 BEGIN_ENTRYPOINT_NOTHROW;
1534
1535 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1536 EventRec *pRec;
1537 HENUMInternal hEnum;
1538
1539 LOG((LOGMD, "MD RegMeta::GetEventProps(0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1540 ev, pClass, MDSTR(szEvent), cchEvent, pchEvent, pdwEventFlags, ptkEventType,
1541 pmdAddOn, pmdRemoveOn, pmdFire, rmdOtherMethod, cMax, pcOtherMethod));
1542
1543 START_MD_PERF();
1544 LOCKREAD();
1545
1546 _ASSERTE(TypeFromToken(ev) == mdtEvent);
1547
1548 memset(&hEnum, 0, sizeof(HENUMInternal));
1549 IfFailGo(pMiniMd->GetEventRecord(RidFromToken(ev), &pRec));
1550
1551 if ( pClass )
1552 {
1553 // find the event map entry corresponding to this event
1554 IfFailGo( pMiniMd->FindParentOfEventHelper( ev, pClass ) );
1555 }
1556 if ( pdwEventFlags )
1557 {
1558 *pdwEventFlags = pMiniMd->getEventFlagsOfEvent(pRec);
1559 }
1560 if ( ptkEventType )
1561 {
1562 *ptkEventType = pMiniMd->getEventTypeOfEvent(pRec);
1563 }
1564 {
1565 MethodSemanticsRec *pSemantics;
1566 RID ridCur;
1567 ULONG cCurOtherMethod = 0;
1568 ULONG ulSemantics;
1569 mdMethodDef tkMethod;
1570
1571 // initialize output parameters
1572 if (pmdAddOn)
1573 *pmdAddOn = mdMethodDefNil;
1574 if (pmdRemoveOn)
1575 *pmdRemoveOn = mdMethodDefNil;
1576 if (pmdFire)
1577 *pmdFire = mdMethodDefNil;
1578
1579 IfFailGo( pMiniMd->FindMethodSemanticsHelper(ev, &hEnum) );
1580 while (HENUMInternal::EnumNext(&hEnum, (mdToken *)&ridCur))
1581 {
1582 IfFailGo(pMiniMd->GetMethodSemanticsRecord(ridCur, &pSemantics));
1583 ulSemantics = pMiniMd->getSemanticOfMethodSemantics(pSemantics);
1584 tkMethod = TokenFromRid( pMiniMd->getMethodOfMethodSemantics(pSemantics), mdtMethodDef );
1585 switch (ulSemantics)
1586 {
1587 case msAddOn:
1588 if (pmdAddOn) *pmdAddOn = tkMethod;
1589 break;
1590 case msRemoveOn:
1591 if (pmdRemoveOn) *pmdRemoveOn = tkMethod;
1592 break;
1593 case msFire:
1594 if (pmdFire) *pmdFire = tkMethod;
1595 break;
1596 case msOther:
1597 if (cCurOtherMethod < cMax)
1598 rmdOtherMethod[cCurOtherMethod] = tkMethod;
1599 cCurOtherMethod++;
1600 break;
1601 default:
1602 _ASSERTE(!"BadKind!");
1603 }
1604 }
1605
1606 // set the output parameter
1607 if (pcOtherMethod)
1608 *pcOtherMethod = cCurOtherMethod;
1609 }
1610 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
1611 if (szEvent || pchEvent)
1612 {
1613 IfFailGo( pMiniMd->getNameOfEvent(pRec, (LPWSTR) szEvent, cchEvent, pchEvent) );
1614 }
1615
1616ErrExit:
1617 HENUMInternal::ClearEnum(&hEnum);
1618 STOP_MD_PERF(GetEventProps);
1619 END_ENTRYPOINT_NOTHROW;
1620
1621 return hr;
1622} // STDMETHODIMP RegMeta::GetEventProps()
1623
1624
1625//*****************************************************************************
1626// given a method, return an arra of event/property tokens for each accessor role
1627// it is defined to have
1628//*****************************************************************************
1629STDMETHODIMP RegMeta::EnumMethodSemantics( // S_OK, S_FALSE, or error.
1630 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
1631 mdMethodDef mb, // [IN] MethodDef to scope the enumeration.
1632 mdToken rEventProp[], // [OUT] Put Event/Property here.
1633 ULONG cMax, // [IN] Max properties to put.
1634 ULONG *pcEventProp) // [OUT] Put # put here.
1635{
1636 HRESULT hr = NOERROR;
1637 BEGIN_ENTRYPOINT_NOTHROW;
1638
1639 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
1640 ULONG ridEnd;
1641 ULONG index;
1642 HENUMInternal *pEnum = *ppmdEnum;
1643 MethodSemanticsRec *pRec;
1644
1645 LOG((LOGMD, "MD RegMeta::EnumMethodSemantics(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1646 phEnum, mb, rEventProp, cMax, pcEventProp));
1647
1648 START_MD_PERF();
1649 LOCKREAD();
1650
1651
1652 if ( pEnum == 0 )
1653 {
1654 // instantiating a new ENUM
1655 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1656
1657 // create the enumerator
1658 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( (DWORD) -1, &pEnum) );
1659
1660 // get the range of method rids given a typedef
1661 ridEnd = pMiniMd->getCountMethodSemantics();
1662
1663 for (index = 1; index <= ridEnd; index++ )
1664 {
1665 IfFailGo(pMiniMd->GetMethodSemanticsRecord(index, &pRec));
1666 if ( pMiniMd->getMethodOfMethodSemantics(pRec) == mb )
1667 {
1668 IfFailGo( HENUMInternal::AddElementToEnum(pEnum, pMiniMd->getAssociationOfMethodSemantics(pRec) ) );
1669 }
1670 }
1671
1672 // set the output parameter
1673 *ppmdEnum = pEnum;
1674 }
1675
1676 // fill the output token buffer
1677 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rEventProp, pcEventProp);
1678
1679ErrExit:
1680 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
1681
1682
1683 STOP_MD_PERF(EnumMethodSemantics);
1684 END_ENTRYPOINT_NOTHROW;
1685
1686 return hr;
1687} // STDMETHODIMP RegMeta::EnumMethodSemantics()
1688
1689
1690
1691//*****************************************************************************
1692// return the role flags for the method/propevent pair
1693//*****************************************************************************
1694STDMETHODIMP RegMeta::GetMethodSemantics( // S_OK, S_FALSE, or error.
1695 mdMethodDef mb, // [IN] method token
1696 mdToken tkEventProp, // [IN] event/property token.
1697 DWORD *pdwSemanticsFlags) // [OUT] the role flags for the method/propevent pair
1698{
1699 HRESULT hr = NOERROR;
1700
1701 BEGIN_ENTRYPOINT_NOTHROW;
1702
1703 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1704 MethodSemanticsRec *pRec;
1705 ULONG ridCur;
1706 HENUMInternal hEnum;
1707
1708 LOG((LOGMD, "MD RegMeta::GetMethodSemantics(0x%08x, 0x%08x, 0x%08x)\n",
1709 mb, tkEventProp, pdwSemanticsFlags));
1710
1711
1712
1713 START_MD_PERF();
1714 LOCKREAD();
1715
1716 _ASSERTE(TypeFromToken(mb) == mdtMethodDef);
1717 _ASSERTE( pdwSemanticsFlags );
1718
1719 *pdwSemanticsFlags = 0;
1720 memset(&hEnum, 0, sizeof(HENUMInternal));
1721
1722 // loop through all methods associated with this tkEventProp
1723 IfFailGo( pMiniMd->FindMethodSemanticsHelper(tkEventProp, &hEnum) );
1724 while (HENUMInternal::EnumNext(&hEnum, (mdToken *)&ridCur))
1725 {
1726 IfFailGo(pMiniMd->GetMethodSemanticsRecord(ridCur, &pRec));
1727 if ( pMiniMd->getMethodOfMethodSemantics(pRec) == mb )
1728 {
1729 // we findd the match
1730 *pdwSemanticsFlags = pMiniMd->getSemanticOfMethodSemantics(pRec);
1731 goto ErrExit;
1732 }
1733 }
1734
1735 IfFailGo( CLDB_E_RECORD_NOTFOUND );
1736
1737ErrExit:
1738 HENUMInternal::ClearEnum(&hEnum);
1739 STOP_MD_PERF(GetMethodSemantics);
1740 END_ENTRYPOINT_NOTHROW;
1741
1742 return hr;
1743} // STDMETHODIMP RegMeta::GetMethodSemantics()
1744
1745
1746
1747//*****************************************************************************
1748// return the class layout information
1749//*****************************************************************************
1750STDMETHODIMP RegMeta::GetClassLayout(
1751 mdTypeDef td, // [IN] give typedef
1752 DWORD *pdwPackSize, // [OUT] 1, 2, 4, 8, or 16
1753 COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array
1754 ULONG cMax, // [IN] size of the array
1755 ULONG *pcFieldOffset, // [OUT] needed array size
1756 ULONG *pulClassSize) // [OUT] the size of the class
1757{
1758 HRESULT hr = NOERROR;
1759
1760 BEGIN_ENTRYPOINT_NOTHROW;
1761
1762 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1763 ClassLayoutRec *pRec;
1764 RID ridClassLayout;
1765 int bLayout=0; // Was any layout information found?
1766
1767 _ASSERTE(TypeFromToken(td) == mdtTypeDef);
1768
1769 LOG((LOGMD, "MD RegMeta::GetClassLayout(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1770 td, pdwPackSize, rFieldOffset, cMax, pcFieldOffset, pulClassSize));
1771
1772 START_MD_PERF();
1773 LOCKREAD();
1774
1775 IfFailGo(pMiniMd->FindClassLayoutHelper(td, &ridClassLayout));
1776
1777 if (InvalidRid(ridClassLayout))
1778 { // Nothing specified - return default values of 0.
1779 if ( pdwPackSize )
1780 *pdwPackSize = 0;
1781 if ( pulClassSize )
1782 *pulClassSize = 0;
1783 }
1784 else
1785 {
1786 IfFailGo(pMiniMd->GetClassLayoutRecord(RidFromToken(ridClassLayout), &pRec));
1787 if ( pdwPackSize )
1788 *pdwPackSize = pMiniMd->getPackingSizeOfClassLayout(pRec);
1789 if ( pulClassSize )
1790 *pulClassSize = pMiniMd->getClassSizeOfClassLayout(pRec);
1791 bLayout = 1;
1792 }
1793
1794 // fill the layout array
1795 if (rFieldOffset || pcFieldOffset)
1796 {
1797 ULONG iFieldOffset = 0;
1798 ULONG ridFieldStart;
1799 ULONG ridFieldEnd;
1800 ULONG ridFieldLayout;
1801 ULONG ulOffset;
1802 TypeDefRec *pTypeDefRec;
1803 FieldLayoutRec *pLayout2Rec;
1804 mdFieldDef fd;
1805
1806 // record for this typedef in TypeDef Table
1807 IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(td), &pTypeDefRec));
1808
1809 // find the starting and end field for this typedef
1810 ridFieldStart = pMiniMd->getFieldListOfTypeDef(pTypeDefRec);
1811 IfFailGo(pMiniMd->getEndFieldListOfTypeDef(RidFromToken(td), &ridFieldEnd));
1812
1813 // loop through the field table
1814
1815 for(; ridFieldStart < ridFieldEnd; ridFieldStart++)
1816 {
1817 // Calculate the field token.
1818 RID rid;
1819 IfFailGo(pMiniMd->GetFieldRid(ridFieldStart, &rid));
1820 fd = TokenFromRid(rid, mdtFieldDef);
1821
1822 // Calculate the FieldLayout rid for the current field.
1823 IfFailGo(pMiniMd->FindFieldLayoutHelper(fd, &ridFieldLayout));
1824
1825 // Calculate the offset.
1826 if (InvalidRid(ridFieldLayout))
1827 ulOffset = (ULONG) -1;
1828 else
1829 {
1830 // get the FieldLayout record.
1831 IfFailGo(pMiniMd->GetFieldLayoutRecord(ridFieldLayout, &pLayout2Rec));
1832 ulOffset = pMiniMd->getOffSetOfFieldLayout(pLayout2Rec);
1833 bLayout = 1;
1834 }
1835
1836 // fill in the field layout if output buffer still has space.
1837 if (cMax > iFieldOffset && rFieldOffset)
1838 {
1839 rFieldOffset[iFieldOffset].ridOfField = fd;
1840 rFieldOffset[iFieldOffset].ulOffset = ulOffset;
1841 }
1842
1843 // advance the index to the buffer.
1844 iFieldOffset++;
1845 }
1846
1847 if (bLayout && pcFieldOffset)
1848 *pcFieldOffset = iFieldOffset;
1849 }
1850
1851 if (!bLayout)
1852 hr = CLDB_E_RECORD_NOTFOUND;
1853
1854ErrExit:
1855 STOP_MD_PERF(GetClassLayout);
1856 END_ENTRYPOINT_NOTHROW;
1857
1858 return hr;
1859} // STDMETHODIMP RegMeta::GetClassLayout()
1860
1861
1862
1863//*****************************************************************************
1864// return the native type of a field
1865//*****************************************************************************
1866STDMETHODIMP RegMeta::GetFieldMarshal(
1867 mdToken tk, // [IN] given a field's memberdef
1868 PCCOR_SIGNATURE *ppvNativeType, // [OUT] native type of this field
1869 ULONG *pcbNativeType) // [OUT] the count of bytes of *ppvNativeType
1870{
1871 HRESULT hr = NOERROR;
1872
1873 BEGIN_ENTRYPOINT_NOTHROW;
1874
1875 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1876 RID rid;
1877 FieldMarshalRec *pFieldMarshalRec;
1878
1879
1880 _ASSERTE(ppvNativeType != NULL && pcbNativeType != NULL);
1881
1882 LOG((LOGMD, "MD RegMeta::GetFieldMarshal(0x%08x, 0x%08x, 0x%08x)\n",
1883 tk, ppvNativeType, pcbNativeType));
1884
1885 START_MD_PERF();
1886 LOCKREAD();
1887
1888 _ASSERTE(TypeFromToken(tk) == mdtParamDef || TypeFromToken(tk) == mdtFieldDef);
1889
1890 // find the row containing the marshal definition for tk
1891 IfFailGo(pMiniMd->FindFieldMarshalHelper(tk, &rid));
1892 if (InvalidRid(rid))
1893 {
1894 IfFailGo( CLDB_E_RECORD_NOTFOUND );
1895 }
1896 IfFailGo(pMiniMd->GetFieldMarshalRecord(rid, &pFieldMarshalRec));
1897
1898 // get the native type
1899 IfFailGo(pMiniMd->getNativeTypeOfFieldMarshal(pFieldMarshalRec, ppvNativeType, pcbNativeType));
1900
1901ErrExit:
1902 STOP_MD_PERF(GetFieldMarshal);
1903 END_ENTRYPOINT_NOTHROW;
1904
1905 return hr;
1906} // STDMETHODIMP RegMeta::GetFieldMarshal()
1907
1908
1909
1910//*****************************************************************************
1911// return the RVA and implflag for MethodDef or FieldDef token
1912//*****************************************************************************
1913STDMETHODIMP
1914RegMeta::GetRVA(
1915 mdToken tk, // Member for which to set offset
1916 ULONG *pulCodeRVA, // The offset
1917 DWORD *pdwImplFlags) // the implementation flags
1918{
1919 HRESULT hr = NOERROR;
1920
1921 BEGIN_ENTRYPOINT_NOTHROW;
1922
1923 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
1924
1925 LOG((LOGMD, "MD RegMeta::GetRVA(0x%08x, 0x%08x, 0x%08x)\n",
1926 tk, pulCodeRVA, pdwImplFlags));
1927
1928 START_MD_PERF();
1929 LOCKREAD();
1930
1931 if (TypeFromToken(tk) == mdtMethodDef)
1932 {
1933 if (tk == mdMethodDefNil)
1934 { // Backward compatibility with CLR 2.0 implementation
1935 if (pulCodeRVA != NULL)
1936 *pulCodeRVA = 0;
1937 if (pdwImplFlags != NULL)
1938 *pdwImplFlags = 0;
1939
1940 hr = S_OK;
1941 goto ErrExit;
1942 }
1943
1944 // MethodDef token
1945 MethodRec *pMethodRec;
1946 IfFailGo(pMiniMd->GetMethodRecord(RidFromToken(tk), &pMethodRec));
1947
1948 if (pulCodeRVA != NULL)
1949 {
1950 *pulCodeRVA = pMiniMd->getRVAOfMethod(pMethodRec);
1951 }
1952 if (pdwImplFlags != NULL)
1953 {
1954 *pdwImplFlags = pMiniMd->getImplFlagsOfMethod(pMethodRec);
1955 }
1956 }
1957 else
1958 { // FieldDef token or invalid type of token (not mdtMethodDef)
1959 ULONG iRecord;
1960
1961 IfFailGo(pMiniMd->FindFieldRVAHelper(tk, &iRecord));
1962
1963 if (InvalidRid(iRecord))
1964 {
1965 if (pulCodeRVA != NULL)
1966 *pulCodeRVA = 0;
1967
1968 IfFailGo(CLDB_E_RECORD_NOTFOUND);
1969 }
1970
1971 FieldRVARec *pFieldRVARec;
1972 IfFailGo(pMiniMd->GetFieldRVARecord(iRecord, &pFieldRVARec));
1973
1974 if (pulCodeRVA != NULL)
1975 {
1976 *pulCodeRVA = pMiniMd->getRVAOfFieldRVA(pFieldRVARec);
1977 }
1978 if (pdwImplFlags != NULL)
1979 {
1980 *pdwImplFlags = 0;
1981 }
1982 }
1983ErrExit:
1984 STOP_MD_PERF(GetRVA);
1985 END_ENTRYPOINT_NOTHROW;
1986
1987 return hr;
1988} // RegMeta::GetRVA
1989
1990
1991
1992//*****************************************************************************
1993// Get the Action and Permissions blob for a given PermissionSet.
1994//*****************************************************************************
1995STDMETHODIMP RegMeta::GetPermissionSetProps(
1996 mdPermission pm, // [IN] the permission token.
1997 DWORD *pdwAction, // [OUT] CorDeclSecurity.
1998 void const **ppvPermission, // [OUT] permission blob.
1999 ULONG *pcbPermission) // [OUT] count of bytes of pvPermission.
2000{
2001 HRESULT hr = S_OK;
2002
2003 BEGIN_ENTRYPOINT_NOTHROW;
2004
2005 LOG((LOGMD, "MD RegMeta::GetPermissionSetProps(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2006 pm, pdwAction, ppvPermission, pcbPermission));
2007
2008 CMiniMdRW *pMiniMd = NULL;
2009 DeclSecurityRec *pRecord = NULL;
2010
2011 START_MD_PERF();
2012 LOCKREAD();
2013
2014 pMiniMd = &(m_pStgdb->m_MiniMd);
2015 IfFailGo(pMiniMd->GetDeclSecurityRecord(RidFromToken(pm), &pRecord));
2016
2017 _ASSERTE(TypeFromToken(pm) == mdtPermission && RidFromToken(pm));
2018
2019 // If you want the BLOB, better get the BLOB size as well.
2020 _ASSERTE(!ppvPermission || pcbPermission);
2021
2022 if (pdwAction)
2023 *pdwAction = pMiniMd->getActionOfDeclSecurity(pRecord);
2024
2025 if (ppvPermission != NULL)
2026 {
2027 IfFailGo(pMiniMd->getPermissionSetOfDeclSecurity(pRecord, (const BYTE **)ppvPermission, pcbPermission));
2028 }
2029
2030ErrExit:
2031
2032 STOP_MD_PERF(GetPermissionSetProps);
2033 END_ENTRYPOINT_NOTHROW;
2034 return hr;
2035} // STDMETHODIMP RegMeta::GetPermissionSetProps()
2036
2037
2038
2039//*****************************************************************************
2040// Given a signature token, get return a pointer to the signature to the caller.
2041//
2042//<TODO>@FUTURE: for short term we have a problem where there is no way to get a
2043// fixed up address for a blob and do Merge at the same time. So we've created
2044// this dummy table called StandAloneSig which you hand out a rid for. This
2045// makes finding the sig an extra indirection that is not required. The
2046// Model Compression save code needs to map the token into a byte offset in
2047// the heap. Perhaps we can have another mdt* type to switch on the difference.
2048// But ultimately it has to simply be "pBlobHeapBase + RidFromToken(mdSig)".</TODO>
2049//*****************************************************************************
2050STDMETHODIMP RegMeta::GetSigFromToken( // S_OK or error.
2051 mdSignature mdSig, // [IN] Signature token.
2052 PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token.
2053 ULONG *pcbSig) // [OUT] return size of signature.
2054{
2055 HRESULT hr = NOERROR;
2056
2057 BEGIN_ENTRYPOINT_NOTHROW;
2058
2059 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2060 StandAloneSigRec *pRec;
2061
2062 LOG((LOGMD, "MD RegMeta::GetSigFromToken(0x%08x, 0x%08x, 0x%08x)\n",
2063 mdSig, ppvSig, pcbSig));
2064
2065
2066
2067 START_MD_PERF();
2068 LOCKREAD();
2069
2070 _ASSERTE(TypeFromToken(mdSig) == mdtSignature);
2071 _ASSERTE(ppvSig && pcbSig);
2072
2073 IfFailGo(pMiniMd->GetStandAloneSigRecord(RidFromToken(mdSig), &pRec));
2074 IfFailGo(pMiniMd->getSignatureOfStandAloneSig(pRec, ppvSig, pcbSig));
2075
2076
2077ErrExit:
2078
2079 STOP_MD_PERF(GetSigFromToken);
2080 END_ENTRYPOINT_NOTHROW;
2081
2082 return hr;
2083} // STDMETHODIMP RegMeta::GetSigFromToken()
2084
2085
2086//*******************************************************************************
2087// return the ModuleRef properties
2088//*******************************************************************************
2089STDMETHODIMP RegMeta::GetModuleRefProps( // S_OK or error.
2090 mdModuleRef mur, // [IN] moduleref token.
2091 __out_ecount_opt (cchName) LPWSTR szName, // [OUT] buffer to fill with the moduleref name.
2092 ULONG cchName, // [IN] size of szName in wide characters.
2093 ULONG *pchName) // [OUT] actual count of characters in the name.
2094{
2095 HRESULT hr = NOERROR;
2096
2097 BEGIN_ENTRYPOINT_NOTHROW;
2098
2099 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2100 ModuleRefRec *pModuleRefRec;
2101
2102
2103
2104 LOG((LOGMD, "MD RegMeta::GetModuleRefProps(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2105 mur, szName, cchName, pchName));
2106 START_MD_PERF();
2107 LOCKREAD();
2108
2109 IfFailGo(pMiniMd->GetModuleRefRecord(RidFromToken(mur), &pModuleRefRec));
2110
2111 _ASSERTE(TypeFromToken(mur) == mdtModuleRef);
2112
2113 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
2114 if (szName || pchName)
2115 {
2116 IfFailGo( pMiniMd->getNameOfModuleRef(pModuleRefRec, szName, cchName, pchName) );
2117 }
2118
2119ErrExit:
2120
2121 STOP_MD_PERF(GetModuleRefProps);
2122 END_ENTRYPOINT_NOTHROW;
2123
2124 return hr;
2125} // STDMETHODIMP RegMeta::GetModuleRefProps()
2126
2127
2128
2129//*******************************************************************************
2130// enumerating through all of the ModuleRefs
2131//*******************************************************************************
2132STDMETHODIMP RegMeta::EnumModuleRefs( // S_OK or error.
2133 HCORENUM *phEnum, // [IN|OUT] pointer to the enum.
2134 mdModuleRef rModuleRefs[], // [OUT] put modulerefs here.
2135 ULONG cMax, // [IN] max memberrefs to put.
2136 ULONG *pcModuleRefs) // [OUT] put # put here.
2137{
2138 HRESULT hr = NOERROR;
2139
2140 BEGIN_ENTRYPOINT_NOTHROW;
2141
2142 HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
2143 HENUMInternal *pEnum;
2144
2145 LOG((LOGMD, "MD RegMeta::EnumModuleRefs(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2146 phEnum, rModuleRefs, cMax, pcModuleRefs));
2147
2148 START_MD_PERF();
2149 LOCKREAD();
2150
2151 if (*ppmdEnum == NULL)
2152 {
2153 // instantiating a new ENUM
2154 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2155
2156 // create the enumerator
2157 IfFailGo(HENUMInternal::CreateSimpleEnum(
2158 mdtModuleRef,
2159 1,
2160 pMiniMd->getCountModuleRefs() + 1,
2161 &pEnum));
2162
2163 // set the output parameter
2164 *ppmdEnum = pEnum;
2165 }
2166 else
2167 {
2168 pEnum = *ppmdEnum;
2169 }
2170
2171 // we can only fill the minimun of what caller asked for or what we have left
2172 IfFailGo(HENUMInternal::EnumWithCount(pEnum, cMax, rModuleRefs, pcModuleRefs));
2173
2174ErrExit:
2175 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
2176
2177 STOP_MD_PERF(EnumModuleRefs);
2178 END_ENTRYPOINT_NOTHROW;
2179
2180 return hr;
2181} // STDMETHODIMP RegMeta::EnumModuleRefs()
2182
2183
2184//*******************************************************************************
2185// return properties regarding a TypeSpec
2186//*******************************************************************************
2187STDMETHODIMP RegMeta::GetTypeSpecFromToken( // S_OK or error.
2188 mdTypeSpec typespec, // [IN] Signature token.
2189 PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token.
2190 ULONG *pcbSig) // [OUT] return size of signature.
2191{
2192 HRESULT hr = NOERROR;
2193
2194 BEGIN_ENTRYPOINT_NOTHROW;
2195
2196 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2197 TypeSpecRec *pRec = NULL;
2198
2199 LOG((LOGMD, "MD RegMeta::GetTypeSpecFromToken(0x%08x, 0x%08x, 0x%08x)\n",
2200 typespec, ppvSig, pcbSig));
2201
2202
2203
2204 START_MD_PERF();
2205 LOCKREAD();
2206
2207 _ASSERTE(TypeFromToken(typespec) == mdtTypeSpec);
2208 _ASSERTE(ppvSig && pcbSig);
2209
2210 IfFailGo(pMiniMd->GetTypeSpecRecord(RidFromToken(typespec), &pRec));
2211 IfFailGo(pMiniMd->getSignatureOfTypeSpec(pRec, ppvSig, pcbSig));
2212
2213ErrExit:
2214
2215 STOP_MD_PERF(GetTypeSpecFromToken);
2216 END_ENTRYPOINT_NOTHROW;
2217 return hr;
2218} // STDMETHODIMP RegMeta::GetTypeSpecFromToken()
2219
2220
2221//*****************************************************************************
2222// For those items that have a name, retrieve a direct pointer to the name
2223// off of the heap. This reduces copies made for the caller.
2224//*****************************************************************************
2225#define NAME_FROM_TOKEN_TYPE(RecType, TokenType) \
2226 case mdt ## TokenType: \
2227 { \
2228 RecType ## Rec *pRecord; \
2229 IfFailGo(pMiniMd->Get ## RecType ## Record(RidFromToken(tk), &pRecord)); \
2230 IfFailGo(pMiniMd->getNameOf ## RecType (pRecord, pszUtf8NamePtr)); \
2231 } \
2232 break;
2233#define NAME_FROM_TOKEN(RecType) NAME_FROM_TOKEN_TYPE(RecType, RecType)
2234
2235STDMETHODIMP RegMeta::GetNameFromToken( // S_OK or error.
2236 mdToken tk, // [IN] Token to get name from. Must have a name.
2237 MDUTF8CSTR *pszUtf8NamePtr) // [OUT] Return pointer to UTF8 name in heap.
2238{
2239 HRESULT hr = S_OK;
2240
2241 BEGIN_ENTRYPOINT_NOTHROW;
2242
2243
2244 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2245
2246 LOG((LOGMD, "MD RegMeta::GetNameFromToken(0x%08x, 0x%08x)\n",
2247 tk, pszUtf8NamePtr));
2248
2249 START_MD_PERF();
2250 LOCKREAD();
2251
2252 _ASSERTE(pszUtf8NamePtr);
2253
2254 switch (TypeFromToken(tk))
2255 {
2256 NAME_FROM_TOKEN(Module);
2257 NAME_FROM_TOKEN(TypeRef);
2258 NAME_FROM_TOKEN(TypeDef);
2259 NAME_FROM_TOKEN_TYPE(Field, FieldDef);
2260 NAME_FROM_TOKEN_TYPE(Method, MethodDef);
2261 NAME_FROM_TOKEN_TYPE(Param, ParamDef);
2262 NAME_FROM_TOKEN(MemberRef);
2263 NAME_FROM_TOKEN(Event);
2264 NAME_FROM_TOKEN(Property);
2265 NAME_FROM_TOKEN(ModuleRef);
2266
2267 default:
2268 hr = E_INVALIDARG;
2269 }
2270
2271ErrExit:
2272
2273 STOP_MD_PERF(GetNameFromToken);
2274
2275 END_ENTRYPOINT_NOTHROW;
2276
2277 return (hr);
2278} // RegMeta::GetNameFromToken
2279
2280
2281//*****************************************************************************
2282// Get the symbol binding data back from the module if it is there. It is
2283// stored as a custom value.
2284//*****************************************************************************
2285STDMETHODIMP RegMeta::EnumUnresolvedMethods( // S_OK or error.
2286 HCORENUM *phEnum, // [IN|OUT] Pointer to the enum.
2287 mdToken rMethods[], // [OUT] Put MemberDefs here.
2288 ULONG cMax, // [IN] Max MemberDefs to put.
2289 ULONG *pcTokens) // [OUT] Put # put here.
2290{
2291#ifdef FEATURE_METADATA_EMIT
2292 HRESULT hr = NOERROR;
2293
2294 BEGIN_ENTRYPOINT_NOTHROW;
2295
2296 HENUMInternal ** ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum);
2297 ULONG iCountTypeDef; // Count of TypeDefs.
2298 ULONG ulStart, ulEnd; // Bounds of methods on a given TypeDef.
2299 ULONG index; // For counting methods on a TypeDef.
2300 ULONG indexTypeDef; // For counting TypeDefs.
2301 bool bIsInterface; // Is a given TypeDef an interface?
2302 HENUMInternal * pEnum = *ppmdEnum; // Enum we're working with.
2303 CMiniMdRW * pMiniMd = &(m_pStgdb->m_MiniMd);
2304
2305 LOG((LOGMD, "MD RegMeta::EnumUnresolvedMethods(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2306 phEnum, rMethods, cMax, pcTokens));
2307
2308 START_MD_PERF();
2309
2310 // take the write lock. Because we should have not have two EnumUnresolvedMethods being called at the
2311 // same time. Ref to Def map may be calculated incorrectly.
2312 LOCKWRITE();
2313
2314 if ( pEnum == 0 )
2315 {
2316 // instantiating a new ENUM
2317 MethodRec *pMethodRec;
2318 TypeDefRec *pTypeDefRec;
2319
2320 // make sure our ref to def optimization is up to date
2321 IfFailGo( RefToDefOptimization() );
2322 IfFailGo( HENUMInternal::CreateDynamicArrayEnum( (DWORD) -1, &pEnum) );
2323
2324 // Loop through all of the methoddef except global functions.
2325 // If methoddef has RVA 0 and not miRuntime, mdAbstract, mdVirtual, mdNative,
2326 // we will fill it into the enumerator.
2327 //
2328 iCountTypeDef = pMiniMd->getCountTypeDefs();
2329
2330 for (indexTypeDef = 2; indexTypeDef <= iCountTypeDef; indexTypeDef ++ )
2331 {
2332 IfFailGo(pMiniMd->GetTypeDefRecord(indexTypeDef, &pTypeDefRec));
2333
2334 // If the type is an interface, check the static methods.
2335 bIsInterface = IsTdInterface(pTypeDefRec->GetFlags());
2336
2337 ulStart = pMiniMd->getMethodListOfTypeDef(pTypeDefRec);
2338 IfFailGo(pMiniMd->getEndMethodListOfTypeDef(indexTypeDef, &ulEnd));
2339
2340 // always report errors even with any unimplemented methods
2341 for (index = ulStart; index < ulEnd; index++)
2342 {
2343 RID methodRid;
2344 IfFailGo(pMiniMd->GetMethodRid(index, &methodRid));
2345 IfFailGo(pMiniMd->GetMethodRecord(methodRid, &pMethodRec));
2346
2347 // If the type is an interface, and the method is not static, on to next.
2348 if (bIsInterface && !IsMdStatic(pMethodRec->GetFlags()))
2349 continue;
2350
2351 if ( IsMiForwardRef(pMethodRec->GetImplFlags()) )
2352 {
2353 if ( IsMdPinvokeImpl(pMethodRec->GetFlags()) )
2354 {
2355 continue;
2356 }
2357 if ( IsMiRuntime(pMethodRec->GetImplFlags()) || IsMiInternalCall(pMethodRec->GetImplFlags()))
2358 {
2359 continue;
2360 }
2361
2362 if (IsMdAbstract(pMethodRec->GetFlags()))
2363 continue;
2364
2365 // If a methoddef has RVA 0 and it is not an abstract or virtual method.
2366 // Nor it is a runtime generated method nore a native method, then we add it
2367 // to the unresolved list.
2368 //
2369 IfFailGo(pMiniMd->GetMethodRid(index, &methodRid));
2370 IfFailGo(HENUMInternal::AddElementToEnum(
2371 pEnum,
2372 TokenFromRid(methodRid, mdtMethodDef)));
2373
2374 LOG((LOGMD, "MD adding unresolved MethodDef: token=%08x, flags=%08x, impl flags=%08x\n",
2375 TokenFromRid(methodRid, mdtMethodDef),
2376 pMethodRec->GetFlags(), pMethodRec->GetImplFlags()));
2377 }
2378 }
2379 }
2380
2381 MemberRefRec *pMemberRefRec;
2382 ULONG iCount;
2383
2384 // loop through MemberRef tables and find all of the unsats
2385 iCount = pMiniMd->getCountMemberRefs();
2386 for (index = 1; index <= iCount; index++ )
2387 {
2388 mdToken defToken;
2389 mdMemberRef refToken = TokenFromRid(index, mdtMemberRef);
2390 IfFailGo(pMiniMd->GetMemberRefRecord(index, &pMemberRefRec));
2391 pMiniMd->GetTokenRemapManager()->ResolveRefToDef(refToken, &defToken);
2392
2393 if ( pMiniMd->getClassOfMemberRef(pMemberRefRec) == m_tdModule && defToken == refToken )
2394 {
2395 // unresovled externals reference if parent token is not resolved and this ref token does not
2396 // map to any def token (can be MethodDef or FieldDef).
2397 //
2398 IfFailGo( HENUMInternal::AddElementToEnum(pEnum, refToken) );
2399
2400 LOG((LOGMD, "MD adding unresolved MemberRef: token=%08x, doesn't have a proper parent\n",
2401 refToken ));
2402 }
2403 }
2404
2405 // set the output parameter
2406 *ppmdEnum = pEnum;
2407 }
2408
2409 // fill the output token buffer
2410 hr = HENUMInternal::EnumWithCount(pEnum, cMax, rMethods, pcTokens);
2411
2412ErrExit:
2413 HENUMInternal::DestroyEnumIfEmpty(ppmdEnum);
2414
2415 STOP_MD_PERF(EnumUnresolvedMethods);
2416 END_ENTRYPOINT_NOTHROW;
2417
2418 return hr;
2419#else //!FEATURE_METADATA_EMIT
2420 return E_NOTIMPL;
2421#endif //!FEATURE_METADATA_EMIT
2422} // RegMeta::EnumUnresolvedMethods
2423
2424//*****************************************************************************
2425// Return the User string given the token. The offset into the Blob pool where
2426// the string is stored in Unicode is embedded inside the token.
2427//*****************************************************************************
2428STDMETHODIMP RegMeta::GetUserString( // S_OK or error.
2429 mdString stk, // [IN] String token.
2430 __out_ecount_opt(cchStringSize) LPWSTR wszString, // [OUT] Copy of string.
2431 ULONG cchStringSize, // [IN] Max chars of room in szString.
2432 ULONG *pcchStringSize) // [OUT] How many chars in actual string.
2433{
2434 HRESULT hr = S_OK;
2435 ULONG cchStringSize_Dummy;
2436 MetaData::DataBlob userString;
2437
2438 BEGIN_ENTRYPOINT_NOTHROW;
2439
2440 LOG((LOGMD, "MD RegMeta::GetUserString(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2441 stk, wszString, cchStringSize, pcchStringSize));
2442
2443 START_MD_PERF();
2444 LOCKREAD();
2445
2446 // Get the string data.
2447 IfFailGo(m_pStgdb->m_MiniMd.GetUserString(RidFromToken(stk), &userString));
2448 // Want to get whole characters, followed by byte to indicate whether there
2449 // are extended characters (>= 0x80).
2450 if ((userString.GetSize() % sizeof(WCHAR)) == 0)
2451 {
2452 Debug_ReportError("User strings should have 1 byte terminator (either 0x00 or 0x80).");
2453 IfFailGo(CLDB_E_FILE_CORRUPT);
2454 }
2455
2456 // Strip off the last byte.
2457 if (!userString.TruncateBySize(1))
2458 {
2459 Debug_ReportInternalError("There's a bug, because previous % 2 check didn't return 0.");
2460 IfFailGo(METADATA_E_INTERNAL_ERROR);
2461 }
2462
2463 // Convert bytes to characters.
2464 if (pcchStringSize == NULL)
2465 {
2466 pcchStringSize = &cchStringSize_Dummy;
2467 }
2468 *pcchStringSize = userString.GetSize() / sizeof(WCHAR);
2469
2470 // Copy the string back to the caller.
2471 if ((wszString != NULL) && (cchStringSize > 0))
2472 {
2473 ULONG cbStringSize = cchStringSize * sizeof(WCHAR);
2474 memcpy(
2475 wszString,
2476 userString.GetDataPointer(),
2477 min(userString.GetSize(), cbStringSize));
2478 if (cbStringSize < userString.GetSize())
2479 {
2480 if ((wszString != NULL) && (cchStringSize > 0))
2481 { // null-terminate the truncated output string
2482 wszString[cchStringSize - 1] = W('\0');
2483 }
2484
2485 hr = CLDB_S_TRUNCATION;
2486 }
2487 }
2488
2489 ErrExit:
2490 STOP_MD_PERF(GetUserString);
2491 END_ENTRYPOINT_NOTHROW;
2492 return hr;
2493} // RegMeta::GetUserString
2494
2495//*****************************************************************************
2496// Return contents of Pinvoke given the forwarded member token.
2497//*****************************************************************************
2498STDMETHODIMP RegMeta::GetPinvokeMap( // S_OK or error.
2499 mdToken tk, // [IN] FieldDef or MethodDef.
2500 DWORD *pdwMappingFlags, // [OUT] Flags used for mapping.
2501 __out_ecount_opt (cchImportName) LPWSTR szImportName, // [OUT] Import name.
2502 ULONG cchImportName, // [IN] Size of the name buffer.
2503 ULONG *pchImportName, // [OUT] Actual number of characters stored.
2504 mdModuleRef *pmrImportDLL) // [OUT] ModuleRef token for the target DLL.
2505{
2506 HRESULT hr = S_OK;
2507
2508 BEGIN_ENTRYPOINT_NOTHROW;
2509
2510 ImplMapRec * pRecord;
2511 ULONG iRecord;
2512
2513 LOG((LOGMD, "MD RegMeta::GetPinvokeMap(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2514 tk, pdwMappingFlags, szImportName, cchImportName, pchImportName, pmrImportDLL));
2515
2516 START_MD_PERF();
2517 LOCKREAD();
2518
2519 _ASSERTE(TypeFromToken(tk) == mdtFieldDef ||
2520 TypeFromToken(tk) == mdtMethodDef);
2521
2522 IfFailGo(m_pStgdb->m_MiniMd.FindImplMapHelper(tk, &iRecord));
2523 if (InvalidRid(iRecord))
2524 {
2525 IfFailGo( CLDB_E_RECORD_NOTFOUND );
2526 }
2527 else
2528 IfFailGo(m_pStgdb->m_MiniMd.GetImplMapRecord(iRecord, &pRecord));
2529
2530 if (pdwMappingFlags)
2531 *pdwMappingFlags = m_pStgdb->m_MiniMd.getMappingFlagsOfImplMap(pRecord);
2532 if (pmrImportDLL)
2533 *pmrImportDLL = m_pStgdb->m_MiniMd.getImportScopeOfImplMap(pRecord);
2534 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
2535 if (szImportName || pchImportName)
2536 IfFailGo(m_pStgdb->m_MiniMd.getImportNameOfImplMap(pRecord, szImportName, cchImportName, pchImportName));
2537ErrExit:
2538 STOP_MD_PERF(GetPinvokeMap);
2539 END_ENTRYPOINT_NOTHROW;
2540
2541 return hr;
2542} // HRESULT RegMeta::GetPinvokeMap()
2543
2544//*****************************************************************************
2545// Enumerate through all the local sigs.
2546//*****************************************************************************
2547STDMETHODIMP RegMeta::EnumSignatures( // S_OK or error.
2548 HCORENUM *phEnum, // [IN|OUT] pointer to the enum.
2549 mdModuleRef rSignatures[], // [OUT] put signatures here.
2550 ULONG cmax, // [IN] max signatures to put.
2551 ULONG *pcSignatures) // [OUT] put # put here.
2552{
2553 HRESULT hr = NOERROR;
2554
2555 BEGIN_ENTRYPOINT_NOTHROW;
2556
2557 HENUMInternal **ppsigEnum = reinterpret_cast<HENUMInternal **> (phEnum);
2558 HENUMInternal *pEnum;
2559
2560 LOG((LOGMD, "MD RegMeta::EnumSignatures(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2561 phEnum, rSignatures, cmax, pcSignatures));
2562
2563 START_MD_PERF();
2564 LOCKREAD();
2565
2566 if (*ppsigEnum == NULL)
2567 {
2568 // instantiating a new ENUM
2569 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2570
2571 // create the enumerator.
2572 IfFailGo(HENUMInternal::CreateSimpleEnum(
2573 mdtSignature,
2574 1,
2575 pMiniMd->getCountStandAloneSigs() + 1,
2576 &pEnum));
2577
2578 // set the output parameter
2579 *ppsigEnum = pEnum;
2580 }
2581 else
2582 {
2583 pEnum = *ppsigEnum;
2584 }
2585
2586 // we can only fill the minimum of what caller asked for or what we have left.
2587 IfFailGo(HENUMInternal::EnumWithCount(pEnum, cmax, rSignatures, pcSignatures));
2588
2589ErrExit:
2590 HENUMInternal::DestroyEnumIfEmpty(ppsigEnum);
2591
2592 STOP_MD_PERF(EnumSignatures);
2593 END_ENTRYPOINT_NOTHROW;
2594
2595 return hr;
2596} // RegMeta::EnumSignatures
2597
2598
2599//*****************************************************************************
2600// Enumerate through all the TypeSpec
2601//*****************************************************************************
2602STDMETHODIMP RegMeta::EnumTypeSpecs( // S_OK or error.
2603 HCORENUM *phEnum, // [IN|OUT] pointer to the enum.
2604 mdTypeSpec rTypeSpecs[], // [OUT] put TypeSpecs here.
2605 ULONG cmax, // [IN] max TypeSpecs to put.
2606 ULONG *pcTypeSpecs) // [OUT] put # put here.
2607{
2608 HRESULT hr = NOERROR;
2609
2610 BEGIN_ENTRYPOINT_NOTHROW;
2611
2612 HENUMInternal **ppEnum = reinterpret_cast<HENUMInternal **> (phEnum);
2613 HENUMInternal *pEnum;
2614
2615 LOG((LOGMD, "MD RegMeta::EnumTypeSpecs(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2616 phEnum, rTypeSpecs, cmax, pcTypeSpecs));
2617
2618 START_MD_PERF();
2619 LOCKREAD();
2620
2621 if (*ppEnum == NULL)
2622 {
2623 // instantiating a new ENUM
2624 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2625
2626 // create the enumerator.
2627 IfFailGo(HENUMInternal::CreateSimpleEnum(
2628 mdtTypeSpec,
2629 1,
2630 pMiniMd->getCountTypeSpecs() + 1,
2631 &pEnum));
2632
2633 // set the output parameter
2634 *ppEnum = pEnum;
2635 }
2636 else
2637 {
2638 pEnum = *ppEnum;
2639 }
2640
2641 // we can only fill the minimum of what caller asked for or what we have left.
2642 IfFailGo(HENUMInternal::EnumWithCount(pEnum, cmax, rTypeSpecs, pcTypeSpecs));
2643
2644ErrExit:
2645 HENUMInternal::DestroyEnumIfEmpty(ppEnum);
2646
2647 STOP_MD_PERF(EnumTypeSpecs);
2648 END_ENTRYPOINT_NOTHROW;
2649
2650 return hr;
2651} // RegMeta::EnumTypeSpecs
2652
2653
2654//*****************************************************************************
2655// Enumerate through all the User Strings.
2656//*****************************************************************************
2657STDMETHODIMP RegMeta::EnumUserStrings( // S_OK or error.
2658 HCORENUM *phEnum, // [IN/OUT] pointer to the enum.
2659 mdString rStrings[], // [OUT] put Strings here.
2660 ULONG cmax, // [IN] max Strings to put.
2661 ULONG *pcStrings) // [OUT] put # put here.
2662{
2663 HRESULT hr = NOERROR;
2664
2665 BEGIN_ENTRYPOINT_NOTHROW;
2666
2667 HENUMInternal **ppEnum = reinterpret_cast<HENUMInternal **> (phEnum);
2668 HENUMInternal *pEnum = *ppEnum;
2669
2670 LOG((LOGMD, "MD RegMeta::EnumUserStrings(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2671 phEnum, rStrings, cmax, pcStrings));
2672
2673 START_MD_PERF();
2674 LOCKREAD();
2675
2676 if (pEnum == NULL)
2677 {
2678 // instantiating a new ENUM.
2679 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2680 IfFailGo(HENUMInternal::CreateDynamicArrayEnum(mdtString, &pEnum));
2681
2682 // Add all strings to the dynamic array
2683 for (UINT32 nIndex = 0; ;)
2684 {
2685 MetaData::DataBlob userString;
2686 UINT32 nNextIndex;
2687 hr = pMiniMd->GetUserStringAndNextIndex(
2688 nIndex,
2689 &userString,
2690 &nNextIndex);
2691 IfFailGo(hr);
2692 if (hr == S_FALSE)
2693 { // We reached the last user string
2694 hr = S_OK;
2695 break;
2696 }
2697 _ASSERTE(hr == S_OK);
2698
2699 // Skip empty strings
2700 if (userString.IsEmpty())
2701 {
2702 nIndex = nNextIndex;
2703 continue;
2704 }
2705 // Add the user string into dynamic array
2706 IfFailGo(HENUMInternal::AddElementToEnum(
2707 pEnum,
2708 TokenFromRid(nIndex, mdtString)));
2709
2710 // Process next user string in the heap
2711 nIndex = nNextIndex;
2712 }
2713
2714 // set the output parameter.
2715 *ppEnum = pEnum;
2716 }
2717
2718 // fill the output token buffer.
2719 hr = HENUMInternal::EnumWithCount(pEnum, cmax, rStrings, pcStrings);
2720
2721ErrExit:
2722 HENUMInternal::DestroyEnumIfEmpty(ppEnum);
2723
2724
2725 STOP_MD_PERF(EnumUserStrings);
2726 END_ENTRYPOINT_NOTHROW;
2727
2728 return hr;
2729} // RegMeta::EnumUserStrings
2730
2731
2732//*****************************************************************************
2733// This routine gets the param token given a method and index of the parameter.
2734//*****************************************************************************
2735STDMETHODIMP RegMeta::GetParamForMethodIndex( // S_OK or error.
2736 mdMethodDef md, // [IN] Method token.
2737 ULONG ulParamSeq, // [IN] Parameter sequence.
2738 mdParamDef *ppd) // [IN] Put Param token here.
2739{
2740 HRESULT hr = S_OK;
2741
2742 BEGIN_ENTRYPOINT_NOTHROW;
2743
2744
2745 LOG((LOGMD, "MD RegMeta::GetParamForMethodIndex(0x%08x, 0x%08x, 0x%08x)\n",
2746 md, ulParamSeq, ppd));
2747
2748 START_MD_PERF();
2749 LOCKREAD();
2750
2751 _ASSERTE((TypeFromToken(md) == mdtMethodDef) && (ulParamSeq != ULONG_MAX) && (ppd != NULL));
2752
2753 IfFailGo(_FindParamOfMethod(md, ulParamSeq, ppd));
2754ErrExit:
2755
2756 STOP_MD_PERF(GetParamForMethodIndex);
2757 END_ENTRYPOINT_NOTHROW;
2758
2759 return hr;
2760} // RegMeta::GetParamForMethodIndex()
2761
2762//*****************************************************************************
2763// Return the property of a MethodDef or a FieldDef
2764//*****************************************************************************
2765HRESULT RegMeta::GetMemberProps(
2766 mdToken mb, // The member for which to get props.
2767 mdTypeDef *pClass, // Put member's class here.
2768 __out_ecount_opt (cchMember) LPWSTR szMember, // Put member's name here.
2769 ULONG cchMember, // Size of szMember buffer in wide chars.
2770 ULONG *pchMember, // Put actual size here
2771 DWORD *pdwAttr, // Put flags here.
2772 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
2773 ULONG *pcbSigBlob, // [OUT] actual size of signature blob
2774 ULONG *pulCodeRVA, // [OUT] codeRVA
2775 DWORD *pdwImplFlags, // [OUT] Impl. Flags
2776 DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_*
2777 UVCP_CONSTANT *ppValue, // [OUT] constant value
2778 ULONG *pchValue) // [OUT] size of constant value, string only, wide chars
2779{
2780 HRESULT hr = NOERROR;
2781
2782 BEGIN_ENTRYPOINT_NOTHROW;
2783
2784 LOG((LOGMD, "MD RegMeta::GetMemberProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2785 mb, pClass, szMember, cchMember, pchMember, pdwAttr, ppvSigBlob, pcbSigBlob,
2786 pulCodeRVA, pdwImplFlags, pdwCPlusTypeFlag, ppValue, pchValue));
2787
2788
2789
2790 START_MD_PERF();
2791
2792 _ASSERTE(TypeFromToken(mb) == mdtMethodDef || TypeFromToken(mb) == mdtFieldDef);
2793
2794 // No need to lock this function. It is calling public APIs. Keep it that way.
2795
2796 if (TypeFromToken(mb) == mdtMethodDef)
2797 {
2798 // It is a Method
2799 IfFailGo( GetMethodProps(
2800 mb,
2801 pClass,
2802 szMember,
2803 cchMember,
2804 pchMember,
2805 pdwAttr,
2806 ppvSigBlob,
2807 pcbSigBlob,
2808 pulCodeRVA,
2809 pdwImplFlags) );
2810 }
2811 else
2812 {
2813 // It is a Field
2814 IfFailGo( GetFieldProps(
2815 mb,
2816 pClass,
2817 szMember,
2818 cchMember,
2819 pchMember,
2820 pdwAttr,
2821 ppvSigBlob,
2822 pcbSigBlob,
2823 pdwCPlusTypeFlag,
2824 ppValue,
2825 pchValue) );
2826 }
2827ErrExit:
2828 STOP_MD_PERF(GetMemberProps);
2829 END_ENTRYPOINT_NOTHROW;
2830
2831 return hr;
2832} // HRESULT RegMeta::GetMemberProps()
2833
2834//*****************************************************************************
2835// Return the property of a FieldDef
2836//*****************************************************************************
2837HRESULT RegMeta::GetFieldProps(
2838 mdFieldDef fd, // The field for which to get props.
2839 mdTypeDef *pClass, // Put field's class here.
2840 __out_ecount_opt (cchField) LPWSTR szField, // Put field's name here.
2841 ULONG cchField, // Size of szField buffer in wide chars.
2842 ULONG *pchField, // Put actual size here
2843 DWORD *pdwAttr, // Put flags here.
2844 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
2845 ULONG *pcbSigBlob, // [OUT] actual size of signature blob
2846 DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_*
2847 UVCP_CONSTANT *ppValue, // [OUT] constant value
2848 ULONG *pchValue) // [OUT] size of constant value, string only, wide chars
2849{
2850 HRESULT hr = NOERROR;
2851
2852 BEGIN_ENTRYPOINT_NOTHROW;
2853
2854 FieldRec *pFieldRec;
2855 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
2856
2857 LOG((LOGMD, "MD RegMeta::GetFieldProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2858 fd, pClass, szField, cchField, pchField, pdwAttr, ppvSigBlob, pcbSigBlob, pdwCPlusTypeFlag,
2859 ppValue, pchValue));
2860
2861 START_MD_PERF();
2862 LOCKREAD();
2863
2864 _ASSERTE(TypeFromToken(fd) == mdtFieldDef);
2865
2866 IfFailGo(pMiniMd->GetFieldRecord(RidFromToken(fd), &pFieldRec));
2867
2868 if (pClass)
2869 {
2870 // caller wants parent typedef
2871 IfFailGo( pMiniMd->FindParentOfFieldHelper(fd, pClass) );
2872
2873 if ( IsGlobalMethodParentToken(*pClass) )
2874 {
2875 // If the parent of Field is the <Module>, return mdTypeDefNil instead.
2876 *pClass = mdTypeDefNil;
2877 }
2878 }
2879 if (ppvSigBlob || pcbSigBlob)
2880 {
2881 // caller wants signature information
2882 PCCOR_SIGNATURE pvSigTmp;
2883 ULONG cbSig;
2884 IfFailGo(pMiniMd->getSignatureOfField(pFieldRec, &pvSigTmp, &cbSig));
2885 if ( ppvSigBlob )
2886 *ppvSigBlob = pvSigTmp;
2887 if ( pcbSigBlob)
2888 *pcbSigBlob = cbSig;
2889 }
2890 if ( pdwAttr )
2891 {
2892 *pdwAttr = pMiniMd->getFlagsOfField(pFieldRec);
2893 }
2894 if ( pdwCPlusTypeFlag || ppValue || pchValue)
2895 {
2896 // get the constant value
2897 ULONG cbValue;
2898 RID rid;
2899 IfFailGo(pMiniMd->FindConstantHelper(fd, &rid));
2900
2901 if (pchValue)
2902 *pchValue = 0;
2903
2904 if (InvalidRid(rid))
2905 {
2906 // There is no constant value associate with it
2907 if (pdwCPlusTypeFlag)
2908 *pdwCPlusTypeFlag = ELEMENT_TYPE_VOID;
2909
2910 if ( ppValue )
2911 *ppValue = NULL;
2912 }
2913 else
2914 {
2915 ConstantRec *pConstantRec;
2916 IfFailGo(m_pStgdb->m_MiniMd.GetConstantRecord(rid, &pConstantRec));
2917 DWORD dwType;
2918
2919 // get the type of constant value
2920 dwType = pMiniMd->getTypeOfConstant(pConstantRec);
2921 if ( pdwCPlusTypeFlag )
2922 *pdwCPlusTypeFlag = dwType;
2923
2924 // get the value blob
2925 if (ppValue != NULL)
2926 {
2927 IfFailGo(pMiniMd->getValueOfConstant(pConstantRec, (const BYTE **)ppValue, &cbValue));
2928 if (pchValue && dwType == ELEMENT_TYPE_STRING)
2929 *pchValue = cbValue / sizeof(WCHAR);
2930 }
2931 }
2932 }
2933 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
2934 if (szField || pchField)
2935 {
2936 IfFailGo( pMiniMd->getNameOfField(pFieldRec, szField, cchField, pchField) );
2937 }
2938
2939ErrExit:
2940 STOP_MD_PERF(GetFieldProps);
2941 END_ENTRYPOINT_NOTHROW;
2942
2943 return hr;
2944} // HRESULT RegMeta::GetFieldProps()
2945
2946//*****************************************************************************
2947// return the properties of a property token
2948//*****************************************************************************
2949HRESULT RegMeta::GetPropertyProps( // S_OK, S_FALSE, or error.
2950 mdProperty prop, // [IN] property token
2951 mdTypeDef *pClass, // [OUT] typedef containing the property declarion.
2952 LPCWSTR szProperty, // [OUT] Property name
2953 ULONG cchProperty, // [IN] the count of wchar of szProperty
2954 ULONG *pchProperty, // [OUT] actual count of wchar for property name
2955 DWORD *pdwPropFlags, // [OUT] property flags.
2956 PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob
2957 ULONG *pbSig, // [OUT] count of bytes in *ppvSig
2958 DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_*
2959 UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value
2960 ULONG *pchDefaultValue, // [OUT] size of constant value, string only, wide chars
2961 mdMethodDef *pmdSetter, // [OUT] setter method of the property
2962 mdMethodDef *pmdGetter, // [OUT] getter method of the property
2963 mdMethodDef rmdOtherMethod[], // [OUT] other method of the property
2964 ULONG cMax, // [IN] size of rmdOtherMethod
2965 ULONG *pcOtherMethod) // [OUT] total number of other method of this property
2966{
2967 HRESULT hr = NOERROR;
2968
2969 BEGIN_ENTRYPOINT_NOTHROW;
2970
2971 CMiniMdRW *pMiniMd;
2972 PropertyRec *pRec;
2973 HENUMInternal hEnum;
2974
2975 LOG((LOGMD, "MD RegMeta::GetPropertyProps(0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, "
2976 "0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, "
2977 "0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, "
2978 "0x%08x)\n",
2979 prop, pClass, MDSTR(szProperty), cchProperty, pchProperty,
2980 pdwPropFlags, ppvSig, pbSig, pdwCPlusTypeFlag, ppDefaultValue,
2981 pchDefaultValue, pmdSetter, pmdGetter, rmdOtherMethod, cMax,
2982 pcOtherMethod));
2983
2984
2985
2986 START_MD_PERF();
2987 LOCKREAD();
2988
2989 _ASSERTE(TypeFromToken(prop) == mdtProperty);
2990
2991 pMiniMd = &(m_pStgdb->m_MiniMd);
2992
2993 memset(&hEnum, 0, sizeof(HENUMInternal));
2994 IfFailGo(pMiniMd->GetPropertyRecord(RidFromToken(prop), &pRec));
2995
2996 if ( pClass )
2997 {
2998 // find the property map entry corresponding to this property
2999 IfFailGo( pMiniMd->FindParentOfPropertyHelper( prop, pClass) );
3000 }
3001 if ( pdwPropFlags )
3002 {
3003 *pdwPropFlags = pMiniMd->getPropFlagsOfProperty(pRec);
3004 }
3005 if ( ppvSig || pbSig )
3006 {
3007 // caller wants the signature
3008 //
3009 ULONG cbSig;
3010 PCCOR_SIGNATURE pvSig;
3011 IfFailGo(pMiniMd->getTypeOfProperty(pRec, &pvSig, &cbSig));
3012 if ( ppvSig )
3013 {
3014 *ppvSig = pvSig;
3015 }
3016 if ( pbSig )
3017 {
3018 *pbSig = cbSig;
3019 }
3020 }
3021 if ( pdwCPlusTypeFlag || ppDefaultValue || pchDefaultValue)
3022 {
3023 // get the constant value
3024 ULONG cbValue;
3025 RID rid;
3026 IfFailGo(pMiniMd->FindConstantHelper(prop, &rid));
3027
3028 if (pchDefaultValue)
3029 *pchDefaultValue = 0;
3030
3031 if (InvalidRid(rid))
3032 {
3033 // There is no constant value associate with it
3034 if (pdwCPlusTypeFlag)
3035 *pdwCPlusTypeFlag = ELEMENT_TYPE_VOID;
3036
3037 if ( ppDefaultValue )
3038 *ppDefaultValue = NULL;
3039 }
3040 else
3041 {
3042 ConstantRec *pConstantRec;
3043 IfFailGo(m_pStgdb->m_MiniMd.GetConstantRecord(rid, &pConstantRec));
3044 DWORD dwType;
3045
3046 // get the type of constant value
3047 dwType = pMiniMd->getTypeOfConstant(pConstantRec);
3048 if ( pdwCPlusTypeFlag )
3049 *pdwCPlusTypeFlag = dwType;
3050
3051 // get the value blob
3052 if (ppDefaultValue != NULL)
3053 {
3054 IfFailGo(pMiniMd->getValueOfConstant(pConstantRec, (const BYTE **)ppDefaultValue, &cbValue));
3055 if (pchDefaultValue && dwType == ELEMENT_TYPE_STRING)
3056 *pchDefaultValue = cbValue / sizeof(WCHAR);
3057 }
3058 }
3059 }
3060 {
3061 MethodSemanticsRec *pSemantics;
3062 RID ridCur;
3063 ULONG cCurOtherMethod = 0;
3064 ULONG ulSemantics;
3065 mdMethodDef tkMethod;
3066
3067 // initialize output parameters
3068 if (pmdSetter)
3069 *pmdSetter = mdMethodDefNil;
3070 if (pmdGetter)
3071 *pmdGetter = mdMethodDefNil;
3072
3073 IfFailGo( pMiniMd->FindMethodSemanticsHelper(prop, &hEnum) );
3074 while (HENUMInternal::EnumNext(&hEnum, (mdToken *)&ridCur))
3075 {
3076 IfFailGo(pMiniMd->GetMethodSemanticsRecord(ridCur, &pSemantics));
3077 ulSemantics = pMiniMd->getSemanticOfMethodSemantics(pSemantics);
3078 tkMethod = TokenFromRid( pMiniMd->getMethodOfMethodSemantics(pSemantics), mdtMethodDef );
3079 switch (ulSemantics)
3080 {
3081 case msSetter:
3082 if (pmdSetter) *pmdSetter = tkMethod;
3083 break;
3084 case msGetter:
3085 if (pmdGetter) *pmdGetter = tkMethod;
3086 break;
3087 case msOther:
3088 if (cCurOtherMethod < cMax)
3089 rmdOtherMethod[cCurOtherMethod] = tkMethod;
3090 cCurOtherMethod ++;
3091 break;
3092 default:
3093 _ASSERTE(!"BadKind!");
3094 }
3095 }
3096
3097 // set the output parameter
3098 if (pcOtherMethod)
3099 *pcOtherMethod = cCurOtherMethod;
3100 }
3101 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
3102 if (szProperty || pchProperty)
3103 {
3104 IfFailGo( pMiniMd->getNameOfProperty(pRec, (LPWSTR) szProperty, cchProperty, pchProperty) );
3105 }
3106
3107ErrExit:
3108 HENUMInternal::ClearEnum(&hEnum);
3109 STOP_MD_PERF(GetPropertyProps);
3110 END_ENTRYPOINT_NOTHROW;
3111
3112 return hr;
3113} // HRESULT RegMeta::GetPropertyProps()
3114
3115
3116//*****************************************************************************
3117// This routine gets the properties for the given Param token.
3118//*****************************************************************************
3119HRESULT RegMeta::GetParamProps( // S_OK or error.
3120 mdParamDef pd, // [IN]The Parameter.
3121 mdMethodDef *pmd, // [OUT] Parent Method token.
3122 ULONG *pulSequence, // [OUT] Parameter sequence.
3123 __out_ecount_opt (cchName) LPWSTR szName, // [OUT] Put name here.
3124 ULONG cchName, // [OUT] Size of name buffer.
3125 ULONG *pchName, // [OUT] Put actual size of name here.
3126 DWORD *pdwAttr, // [OUT] Put flags here.
3127 DWORD *pdwCPlusTypeFlag, // [OUT] Flag for value type. selected ELEMENT_TYPE_*.
3128 UVCP_CONSTANT *ppValue, // [OUT] Constant value.
3129 ULONG *pchValue) // [OUT] size of constant value, string only, wide chars
3130{
3131 HRESULT hr = NOERROR;
3132
3133 BEGIN_ENTRYPOINT_NOTHROW;
3134
3135 ParamRec *pParamRec;
3136 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
3137
3138 LOG((LOGMD, "MD RegMeta::GetParamProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
3139 pd, pmd, pulSequence, szName, cchName, pchName, pdwAttr, pdwCPlusTypeFlag, ppValue, pchValue));
3140
3141 START_MD_PERF();
3142 LOCKREAD();
3143
3144 _ASSERTE(TypeFromToken(pd) == mdtParamDef);
3145
3146 IfFailGo(pMiniMd->GetParamRecord(RidFromToken(pd), &pParamRec));
3147
3148 if (pmd)
3149 {
3150 IfFailGo(pMiniMd->FindParentOfParamHelper(pd, pmd));
3151 _ASSERTE(TypeFromToken(*pmd) == mdtMethodDef);
3152 }
3153 if (pulSequence)
3154 *pulSequence = pMiniMd->getSequenceOfParam(pParamRec);
3155 if (pdwAttr)
3156 {
3157 *pdwAttr = pMiniMd->getFlagsOfParam(pParamRec);
3158 }
3159 if ( pdwCPlusTypeFlag || ppValue || pchValue)
3160 {
3161 // get the constant value
3162 ULONG cbValue;
3163 RID rid;
3164 IfFailGo(pMiniMd->FindConstantHelper(pd, &rid));
3165
3166 if (pchValue)
3167 *pchValue = 0;
3168
3169 if (InvalidRid(rid))
3170 {
3171 // There is no constant value associate with it
3172 if (pdwCPlusTypeFlag)
3173 *pdwCPlusTypeFlag = ELEMENT_TYPE_VOID;
3174
3175 if ( ppValue )
3176 *ppValue = NULL;
3177 }
3178 else
3179 {
3180 ConstantRec *pConstantRec;
3181 IfFailGo(m_pStgdb->m_MiniMd.GetConstantRecord(rid, &pConstantRec));
3182 DWORD dwType;
3183
3184 // get the type of constant value
3185 dwType = pMiniMd->getTypeOfConstant(pConstantRec);
3186 if ( pdwCPlusTypeFlag )
3187 *pdwCPlusTypeFlag = dwType;
3188
3189 // get the value blob
3190 if (ppValue != NULL)
3191 {
3192 IfFailGo(pMiniMd->getValueOfConstant(pConstantRec, (const BYTE **)ppValue, &cbValue));
3193 if (pchValue && dwType == ELEMENT_TYPE_STRING)
3194 *pchValue = cbValue / sizeof(WCHAR);
3195 }
3196 }
3197 }
3198 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
3199 if (szName || pchName)
3200 IfFailGo( pMiniMd->getNameOfParam(pParamRec, szName, cchName, pchName) );
3201
3202ErrExit:
3203 STOP_MD_PERF(GetParamProps);
3204 END_ENTRYPOINT_NOTHROW;
3205
3206 return hr;
3207} // HRESULT RegMeta::GetParamProps()
3208
3209//*****************************************************************************
3210// This routine gets the properties for the given GenericParam token.
3211//*****************************************************************************
3212HRESULT RegMeta::GetGenericParamProps( // S_OK or error.
3213 mdGenericParam rd, // [IN] The type parameter
3214 ULONG* pulSequence, // [OUT] Parameter sequence number
3215 DWORD* pdwAttr, // [OUT] Type parameter flags (for future use)
3216 mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef)
3217 DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use)
3218 __out_ecount_opt (cchName) LPWSTR szName, // [OUT] The name
3219 ULONG cchName, // [IN] Size of name buffer
3220 ULONG *pchName) // [OUT] Actual size of name
3221{
3222 HRESULT hr = NOERROR;
3223
3224 BEGIN_ENTRYPOINT_NOTHROW;
3225
3226 GenericParamRec *pGenericParamRec;
3227 CMiniMdRW *pMiniMd = NULL;
3228 RID ridRD = RidFromToken(rd);
3229
3230
3231 LOG((LOGMD, "MD RegMeta::GetGenericParamProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
3232 rd, pulSequence, pdwAttr, ptOwner, reserved, szName, cchName, pchName));
3233
3234 START_MD_PERF();
3235 LOCKREAD();
3236
3237 pMiniMd = &(m_pStgdb->m_MiniMd);
3238
3239 // See if this version of the metadata can do Generics
3240 if (!pMiniMd->SupportsGenerics())
3241 IfFailGo(CLDB_E_INCOMPATIBLE);
3242
3243
3244 if((TypeFromToken(rd) == mdtGenericParam) && (ridRD != 0))
3245 {
3246 IfFailGo(pMiniMd->GetGenericParamRecord(RidFromToken(rd), &pGenericParamRec));
3247
3248 if (pulSequence)
3249 *pulSequence = pMiniMd->getNumberOfGenericParam(pGenericParamRec);
3250 if (pdwAttr)
3251 *pdwAttr = pMiniMd->getFlagsOfGenericParam(pGenericParamRec);
3252 if (ptOwner)
3253 *ptOwner = pMiniMd->getOwnerOfGenericParam(pGenericParamRec);
3254 // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK
3255 if (pchName || szName)
3256 IfFailGo(pMiniMd->getNameOfGenericParam(pGenericParamRec, szName, cchName, pchName));
3257 }
3258 else
3259 hr = META_E_BAD_INPUT_PARAMETER;
3260
3261ErrExit:
3262 STOP_MD_PERF(GetGenericParamProps);
3263 END_ENTRYPOINT_NOTHROW;
3264
3265 return hr;
3266} // HRESULT RegMeta::GetGenericParamProps()
3267
3268//*****************************************************************************
3269// This routine gets the properties for the given GenericParamConstraint token.
3270//*****************************************************************************
3271HRESULT RegMeta::GetGenericParamConstraintProps( // S_OK or error.
3272 mdGenericParamConstraint rd, // [IN] The constraint token
3273 mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained
3274 mdToken *ptkConstraintType) // [OUT] TypeDef/Ref/Spec constraint
3275{
3276 HRESULT hr = NOERROR;
3277
3278 BEGIN_ENTRYPOINT_NOTHROW;
3279
3280 GenericParamConstraintRec *pGPCRec;
3281 CMiniMdRW *pMiniMd = NULL;
3282 RID ridRD = RidFromToken(rd);
3283
3284 LOG((LOGMD, "MD RegMeta::GetGenericParamConstraintProps(0x%08x, 0x%08x, 0x%08x)\n",
3285 rd, ptGenericParam, ptkConstraintType));
3286
3287 START_MD_PERF();
3288 LOCKREAD();
3289
3290 pMiniMd = &(m_pStgdb->m_MiniMd);
3291
3292 // See if this version of the metadata can do Generics
3293 if (!pMiniMd->SupportsGenerics())
3294 IfFailGo(CLDB_E_INCOMPATIBLE);
3295
3296
3297 if((TypeFromToken(rd) == mdtGenericParamConstraint) && (ridRD != 0))
3298 {
3299 IfFailGo(pMiniMd->GetGenericParamConstraintRecord(ridRD, &pGPCRec));
3300
3301 if (ptGenericParam)
3302 *ptGenericParam = TokenFromRid(pMiniMd->getOwnerOfGenericParamConstraint(pGPCRec),mdtGenericParam);
3303 if (ptkConstraintType)
3304 *ptkConstraintType = pMiniMd->getConstraintOfGenericParamConstraint(pGPCRec);
3305 }
3306 else
3307 hr = META_E_BAD_INPUT_PARAMETER;
3308
3309ErrExit:
3310 STOP_MD_PERF(GetGenericParamConstraintProps);
3311 END_ENTRYPOINT_NOTHROW;
3312
3313 return hr;
3314} // HRESULT RegMeta::GetGenericParamConstraintProps()
3315
3316//*****************************************************************************
3317// This routine gets the properties for the given MethodSpec token.
3318//*****************************************************************************
3319HRESULT RegMeta::GetMethodSpecProps( // S_OK or error.
3320 mdMethodSpec mi, // [IN] The method instantiation
3321 mdToken *tkParent, // [OUT] MethodDef or MemberRef
3322 PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data
3323 ULONG *pcbSigBlob) // [OUT] actual size of signature blob
3324{
3325 HRESULT hr = NOERROR;
3326
3327 BEGIN_ENTRYPOINT_NOTHROW;
3328
3329 MethodSpecRec *pMethodSpecRec;
3330 CMiniMdRW *pMiniMd = NULL;
3331
3332 LOG((LOGMD, "MD RegMeta::GetMethodSpecProps(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
3333 mi, tkParent, ppvSigBlob, pcbSigBlob));
3334 START_MD_PERF();
3335 LOCKREAD();
3336
3337 pMiniMd = &(m_pStgdb->m_MiniMd);
3338
3339
3340 // See if this version of the metadata can do Generics
3341 if (!pMiniMd->SupportsGenerics())
3342 IfFailGo(CLDB_E_INCOMPATIBLE);
3343
3344 _ASSERTE(TypeFromToken(mi) == mdtMethodSpec && RidFromToken(mi));
3345
3346 IfFailGo(pMiniMd->GetMethodSpecRecord(RidFromToken(mi), &pMethodSpecRec));
3347
3348 if (tkParent)
3349 *tkParent = pMiniMd->getMethodOfMethodSpec(pMethodSpecRec);
3350
3351 if (ppvSigBlob || pcbSigBlob)
3352 {
3353 // caller wants signature information
3354 PCCOR_SIGNATURE pvSigTmp;
3355 ULONG cbSig;
3356 IfFailGo(pMiniMd->getInstantiationOfMethodSpec(pMethodSpecRec, &pvSigTmp, &cbSig));
3357 if ( ppvSigBlob )
3358 *ppvSigBlob = pvSigTmp;
3359 if ( pcbSigBlob)
3360 *pcbSigBlob = cbSig;
3361 }
3362
3363
3364ErrExit:
3365
3366 STOP_MD_PERF(GetMethodSpecProps);
3367 END_ENTRYPOINT_NOTHROW;
3368
3369 return hr;
3370} // HRESULT RegMeta::GetMethodSpecProps()
3371
3372//*****************************************************************************
3373// This routine gets the type and machine of the PE file the scope is opened on.
3374//*****************************************************************************
3375HRESULT RegMeta::GetPEKind( // S_OK or error.
3376 DWORD *pdwPEKind, // [OUT] The kind of PE (0 - not a PE)
3377 DWORD *pdwMachine) // [OUT] Machine as defined in NT header
3378{
3379 HRESULT hr = NOERROR;
3380 MAPPINGTYPE mt = MTYPE_NOMAPPING;
3381
3382 BEGIN_ENTRYPOINT_NOTHROW;
3383
3384 LOG((LOGMD, "MD RegMeta::GetPEKind(0x%08x, 0x%08x)\n",pdwPEKind,pdwMachine));
3385
3386 START_MD_PERF();
3387 LOCKREAD();
3388
3389
3390 if (m_pStgdb->m_pStgIO != NULL)
3391 mt = m_pStgdb->m_pStgIO->GetMemoryMappedType();
3392
3393 hr = m_pStgdb->GetPEKind(mt, pdwPEKind, pdwMachine);
3394
3395 ErrExit:
3396
3397 STOP_MD_PERF(GetPEKind);
3398 END_ENTRYPOINT_NOTHROW;
3399 return hr;
3400} // HRESULT RegMeta::GetPEKind()
3401
3402//*****************************************************************************
3403// This function gets the "built for" version of a metadata scope.
3404// NOTE: if the scope has never been saved, it will not have a built-for
3405// version, and an empty string will be returned.
3406//*****************************************************************************
3407HRESULT RegMeta::GetVersionString( // S_OK or error.
3408 __out_ecount_opt (cchBufSize) LPWSTR pwzBuf, // [OUT] Put version string here.
3409 DWORD cchBufSize, // [in] size of the buffer, in wide chars
3410 DWORD *pchBufSize) // [out] Size of the version string, wide chars, including terminating nul.
3411{
3412 HRESULT hr = NOERROR;
3413
3414 BEGIN_ENTRYPOINT_NOTHROW;
3415 REGMETA_POSSIBLE_INTERNAL_POINTER_EXPOSED();
3416
3417 DWORD cch; // Length of WideChar string.
3418 LPCSTR pVer; // Pointer to version string.
3419
3420 LOG((LOGMD, "MD RegMeta::GetVersionString(0x%08x, 0x%08x, 0x%08x)\n",pwzBuf,cchBufSize,pchBufSize));
3421
3422 START_MD_PERF();
3423 LOCKREAD();
3424
3425 if (m_pStgdb->m_pvMd != NULL)
3426 {
3427 // For convenience, get a pointer to the version string.
3428 // @todo: get from alternate locations when there is no STOREAGESIGNATURE.
3429 pVer = reinterpret_cast<const char*>(reinterpret_cast<const STORAGESIGNATURE*>(m_pStgdb->m_pvMd)->pVersion);
3430 // Attempt to convert into caller's buffer.
3431 cch = WszMultiByteToWideChar(CP_UTF8,0, pVer,-1, pwzBuf,cchBufSize);
3432 // Did the string fit?
3433 if (cch == 0)
3434 { // No, didn't fit. Find out space required.
3435 cch = WszMultiByteToWideChar(CP_UTF8,0, pVer,-1, pwzBuf,0);
3436 // NUL terminate string.
3437 if (cchBufSize > 0)
3438 pwzBuf[cchBufSize-1] = W('\0');
3439 // Truncation return code.
3440 hr = CLDB_S_TRUNCATION;
3441 }
3442 }
3443 else
3444 { // No string.
3445 if (cchBufSize > 0)
3446 *pwzBuf = W('\0');
3447 cch = 0;
3448 }
3449
3450 if (pchBufSize)
3451 *pchBufSize = cch;
3452
3453ErrExit:
3454
3455 STOP_MD_PERF(GetVersionString);
3456 END_ENTRYPOINT_NOTHROW;
3457 return hr;
3458} // HRESULT RegMeta::GetVersionString()
3459
3460//*****************************************************************************
3461// This routine gets the parent class for the nested class.
3462//*****************************************************************************
3463HRESULT RegMeta::GetNestedClassProps( // S_OK or error.
3464 mdTypeDef tdNestedClass, // [IN] NestedClass token.
3465 mdTypeDef *ptdEnclosingClass) // [OUT] EnclosingClass token.
3466{
3467 HRESULT hr = NOERROR;
3468
3469 BEGIN_ENTRYPOINT_NOTHROW;
3470
3471 NestedClassRec *pRecord;
3472 ULONG iRecord;
3473 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
3474
3475
3476 LOG((LOGMD, "MD RegMeta::GetNestedClassProps(0x%08x, 0x%08x)\n",
3477 tdNestedClass, ptdEnclosingClass));
3478
3479 START_MD_PERF();
3480 LOCKREAD();
3481
3482 // If not a typedef -- return error.
3483 if (TypeFromToken(tdNestedClass) != mdtTypeDef)
3484 {
3485 IfFailGo(META_E_INVALID_TOKEN_TYPE); // PostError(META_E_INVALID_TOKEN_TYPE, tdNestedClass));
3486 }
3487
3488 _ASSERTE(TypeFromToken(tdNestedClass) && !IsNilToken(tdNestedClass) && ptdEnclosingClass);
3489
3490 IfFailGo(pMiniMd->FindNestedClassHelper(tdNestedClass, &iRecord));
3491
3492 if (InvalidRid(iRecord))
3493 {
3494 hr = CLDB_E_RECORD_NOTFOUND;
3495 goto ErrExit;
3496 }
3497
3498 IfFailGo(pMiniMd->GetNestedClassRecord(iRecord, &pRecord));
3499
3500 _ASSERTE(tdNestedClass == pMiniMd->getNestedClassOfNestedClass(pRecord));
3501 *ptdEnclosingClass = pMiniMd->getEnclosingClassOfNestedClass(pRecord);
3502
3503ErrExit:
3504 STOP_MD_PERF(GetNestedClassProps);
3505 END_ENTRYPOINT_NOTHROW;
3506
3507 return hr;
3508} // HRESULT RegMeta::GetNestedClassProps()
3509
3510//*****************************************************************************
3511// Given a signature, parse it for custom modifier with calling convention.
3512//*****************************************************************************
3513HRESULT RegMeta::GetNativeCallConvFromSig( // S_OK or error.
3514 void const *pvSig, // [IN] Pointer to signature.
3515 ULONG cbSig, // [IN] Count of signature bytes.
3516 ULONG *pCallConv) // [OUT] Put calling conv here (see CorPinvokemap).
3517{
3518 HRESULT hr = NOERROR;
3519
3520 BEGIN_ENTRYPOINT_NOTHROW;
3521
3522 PCCOR_SIGNATURE pvSigBlob = reinterpret_cast<PCCOR_SIGNATURE>(pvSig);
3523 ULONG cbTotal = 0; // total of number bytes for return type + all fixed arguments
3524 ULONG cbCur = 0; // index through the pvSigBlob
3525 ULONG cb;
3526 ULONG cArg;
3527 ULONG cTyArg = 0;
3528 ULONG callingconv;
3529 ULONG cArgsIndex;
3530 ULONG callConv = pmCallConvWinapi; // The calling convention.
3531
3532
3533
3534
3535 *pCallConv = pmCallConvWinapi;
3536
3537 // remember the number of bytes to represent the calling convention
3538 cb = CorSigUncompressData (pvSigBlob, &callingconv);
3539 if (cb == ((ULONG)(-1)))
3540 {
3541 hr = CORSEC_E_INVALID_IMAGE_FORMAT;
3542 goto ErrExit;
3543 }
3544 cbCur += cb;
3545
3546 // remember the number of bytes to represent the type parameter count
3547 if (callingconv & IMAGE_CEE_CS_CALLCONV_GENERIC)
3548 {
3549 cb= CorSigUncompressData (&pvSigBlob[cbCur], &cTyArg);
3550 if (cb == ((ULONG)(-1)))
3551 {
3552 hr = CORSEC_E_INVALID_IMAGE_FORMAT;
3553 goto ErrExit;
3554 }
3555 cbCur += cb;
3556 }
3557
3558
3559 // remember number of bytes to represent the arg counts
3560 cb= CorSigUncompressData (&pvSigBlob[cbCur], &cArg);
3561 if (cb == ((ULONG)(-1)))
3562 {
3563 hr = CORSEC_E_INVALID_IMAGE_FORMAT;
3564 goto ErrExit;
3565 }
3566
3567 cbCur += cb;
3568
3569 // Look at the return type.
3570 hr = _SearchOneArgForCallConv( &pvSigBlob[cbCur], &cb, &callConv);
3571 if (hr == (HRESULT)-1)
3572 {
3573 *pCallConv = callConv;
3574 hr = S_OK;
3575 goto ErrExit;
3576 }
3577 IfFailGo(hr);
3578 cbCur += cb;
3579 cbTotal += cb;
3580
3581 // loop through argument until we found ELEMENT_TYPE_SENTINEL or run
3582 // out of arguments
3583 for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++)
3584 {
3585 _ASSERTE(cbCur < cbSig);
3586 hr = _SearchOneArgForCallConv( &pvSigBlob[cbCur], &cb, &callConv);
3587 if (hr == (HRESULT)-1)
3588 {
3589 *pCallConv = callConv;
3590 hr = S_OK;
3591 goto ErrExit;
3592 }
3593 IfFailGo(hr);
3594 cbTotal += cb;
3595 cbCur += cb;
3596 }
3597
3598ErrExit:
3599 END_ENTRYPOINT_NOTHROW;
3600
3601 return hr;
3602} // HRESULT RegMeta::GetNativeCallConvFromSig()
3603
3604//*****************************************************************************
3605// Helper used by GetNativeCallingConvFromSig.
3606//*****************************************************************************
3607HRESULT RegMeta::_CheckCmodForCallConv( // S_OK, -1 if found, or error.
3608 PCCOR_SIGNATURE pbSig, // [IN] Signature to check.
3609 ULONG *pcbTotal, // [OUT] Put bytes consumed here.
3610 ULONG *pCallConv) // [OUT] If found, put calling convention here.
3611{
3612 ULONG cbTotal = 0; // Bytes consumed.
3613 mdToken tk; // Token for callconv.
3614 HRESULT hr = NOERROR; // A result.
3615 LPCUTF8 szName=0; // Callconv name.
3616 LPCUTF8 szNamespace=0; // Callconv namespace.
3617 CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd);
3618
3619 _ASSERTE(pcbTotal);
3620
3621
3622
3623
3624 // count the bytes for the token compression
3625 cbTotal += CorSigUncompressToken(&pbSig[cbTotal], &tk);
3626
3627 // workaround to skip nil tokens and TypeSpec tokens.
3628 if (IsNilToken(tk) || TypeFromToken(tk) == mdtTypeSpec)
3629 {
3630 *pcbTotal = cbTotal;
3631 goto ErrExit;
3632 }
3633
3634 // See if this token is a calling convention.
3635 if (TypeFromToken(tk) == mdtTypeRef)
3636 {
3637 TypeRefRec *pTypeRefRec;
3638 IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tk), &pTypeRefRec));
3639 IfFailGo(pMiniMd->getNameOfTypeRef(pTypeRefRec, &szName));
3640 IfFailGo(pMiniMd->getNamespaceOfTypeRef(pTypeRefRec, &szNamespace));
3641 }
3642 else
3643 if (TypeFromToken(tk) == mdtTypeDef)
3644 {
3645 TypeDefRec *pTypeDefRec;
3646 IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(tk), &pTypeDefRec));
3647 IfFailGo(pMiniMd->getNameOfTypeDef(pTypeDefRec, &szName));
3648 IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeDefRec, &szNamespace));
3649 }
3650
3651 if ((szNamespace && szName) &&
3652 (strcmp(szNamespace, CMOD_CALLCONV_NAMESPACE) == 0 ||
3653 strcmp(szNamespace, CMOD_CALLCONV_NAMESPACE_OLD) == 0) )
3654 {
3655 // Set the hr to -1, which is an unspecified 'error'. This will percolate
3656 // back up to the caller, where the 'error' should be recognized.
3657 hr=(HRESULT)-1;
3658 if (strcmp(szName, CMOD_CALLCONV_NAME_CDECL) == 0)
3659 *pCallConv = pmCallConvCdecl;
3660 else
3661 if (strcmp(szName, CMOD_CALLCONV_NAME_STDCALL) == 0)
3662 *pCallConv = pmCallConvStdcall;
3663 else
3664 if (strcmp(szName, CMOD_CALLCONV_NAME_THISCALL) == 0)
3665 *pCallConv = pmCallConvThiscall;
3666 else
3667 if (strcmp(szName, CMOD_CALLCONV_NAME_FASTCALL) == 0)
3668 *pCallConv = pmCallConvFastcall;
3669 else
3670 hr = S_OK; // keep looking
3671 IfFailGo(hr);
3672 }
3673 *pcbTotal = cbTotal;
3674
3675ErrExit:
3676
3677 return hr;
3678} // HRESULT RegMeta::_CheckCmodForCallConv()
3679
3680//*****************************************************************************
3681// Helper used by GetNativeCallingConvFromSig.
3682//*****************************************************************************
3683HRESULT RegMeta::_SearchOneArgForCallConv(// S_OK, -1 if found, or error.
3684 PCCOR_SIGNATURE pbSig, // [IN] Signature to check.
3685 ULONG *pcbTotal, // [OUT] Put bytes consumed here.
3686 ULONG *pCallConv) // [OUT] If found, put calling convention here.
3687{
3688 ULONG cb;
3689 ULONG cbTotal = 0;
3690 CorElementType ulElementType;
3691 ULONG ulData;
3692 ULONG ulTemp;
3693 int iData;
3694 mdToken tk;
3695 ULONG cArg;
3696 ULONG callingconv;
3697 ULONG cArgsIndex;
3698 HRESULT hr = NOERROR;
3699
3700 _ASSERTE(pcbTotal);
3701
3702 cbTotal += CorSigUncompressElementType(&pbSig[cbTotal], &ulElementType);
3703 while (CorIsModifierElementType(ulElementType) || ulElementType == ELEMENT_TYPE_SENTINEL)
3704 {
3705 cbTotal += CorSigUncompressElementType(&pbSig[cbTotal], &ulElementType);
3706 }
3707 switch (ulElementType)
3708 {
3709 case ELEMENT_TYPE_SZARRAY:
3710 // skip over base type
3711 IfFailGo( _SearchOneArgForCallConv(&pbSig[cbTotal], &cb, pCallConv) );
3712 cbTotal += cb;
3713 break;
3714
3715 case ELEMENT_TYPE_VAR :
3716 case ELEMENT_TYPE_MVAR :
3717 // skip over index
3718 cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData);
3719 break;
3720
3721 case ELEMENT_TYPE_GENERICINST :
3722 // skip over generic type
3723 IfFailGo( _SearchOneArgForCallConv(&pbSig[cbTotal], &cb, pCallConv) );
3724 cbTotal += cb;
3725
3726 // skip over number of parameters
3727 cbTotal += CorSigUncompressData(&pbSig[cbTotal], &cArg);
3728
3729 // loop through type parameters
3730 for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++)
3731 {
3732 IfFailGo( _SearchOneArgForCallConv( &pbSig[cbTotal], &cb, pCallConv) );
3733 cbTotal += cb;
3734 }
3735
3736 break;
3737
3738 case ELEMENT_TYPE_FNPTR:
3739 cbTotal += CorSigUncompressData (&pbSig[cbTotal], &callingconv);
3740
3741 // remember number of bytes to represent the arg counts
3742 cbTotal += CorSigUncompressData (&pbSig[cbTotal], &cArg);
3743
3744 // how many bytes to represent the return type
3745 IfFailGo( _SearchOneArgForCallConv( &pbSig[cbTotal], &cb, pCallConv) );
3746 cbTotal += cb;
3747
3748 // loop through argument
3749 for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++)
3750 {
3751 IfFailGo( _SearchOneArgForCallConv( &pbSig[cbTotal], &cb, pCallConv) );
3752 cbTotal += cb;
3753 }
3754
3755 break;
3756
3757 case ELEMENT_TYPE_ARRAY:
3758 // syntax : ARRAY BaseType <rank> [i size_1... size_i] [j lowerbound_1 ... lowerbound_j]
3759
3760 // skip over base type
3761 IfFailGo( _SearchOneArgForCallConv(&pbSig[cbTotal], &cb, pCallConv) );
3762 cbTotal += cb;
3763
3764 // Parse for the rank
3765 cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData);
3766
3767 // if rank == 0, we are done
3768 if (ulData == 0)
3769 break;
3770
3771 // any size of dimension specified?
3772 cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData);
3773 while (ulData--)
3774 {
3775 cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulTemp);
3776 }
3777
3778 // any lower bound specified?
3779 cbTotal = CorSigUncompressData(&pbSig[cbTotal], &ulData);
3780
3781 while (ulData--)
3782 {
3783 cbTotal += CorSigUncompressSignedInt(&pbSig[cbTotal], &iData);
3784 }
3785
3786 break;
3787 case ELEMENT_TYPE_VALUETYPE:
3788 case ELEMENT_TYPE_CLASS:
3789 // count the bytes for the token compression
3790 cbTotal += CorSigUncompressToken(&pbSig[cbTotal], &tk);
3791 break;
3792 case ELEMENT_TYPE_CMOD_REQD:
3793 case ELEMENT_TYPE_CMOD_OPT:
3794 // Check for the calling convention.
3795 IfFailGo(_CheckCmodForCallConv(&pbSig[cbTotal], &cb, pCallConv));
3796 cbTotal += cb;
3797 // skip over base type
3798 IfFailGo( _SearchOneArgForCallConv(&pbSig[cbTotal], &cb, pCallConv) );
3799 cbTotal += cb;
3800 break;
3801 default:
3802 break;
3803 }
3804 *pcbTotal = cbTotal;
3805
3806ErrExit:
3807
3808 return hr;
3809} // HRESULT RegMeta::_SearchOneArgForCallConv()
3810