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 | //***************************************************************************** |
29 | STDMETHODIMP 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 | |
104 | ErrExit: |
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 | //***************************************************************************** |
117 | STDMETHODIMP 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 | |
223 | ErrExit: |
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 | //***************************************************************************** |
235 | STDMETHODIMP 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 | |
317 | ErrExit: |
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 | //***************************************************************************** |
332 | STDMETHODIMP 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 | |
419 | ErrExit: |
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 | //***************************************************************************** |
433 | STDMETHODIMP |
434 | RegMeta::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 | |
514 | ErrExit: |
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 | //***************************************************************************** |
528 | STDMETHODIMP 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 | |
613 | ErrExit: |
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 | //***************************************************************************** |
626 | STDMETHODIMP 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 | |
683 | ErrExit: |
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 | //***************************************************************************** |
697 | STDMETHODIMP 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 | |
757 | ErrExit: |
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 | //***************************************************************************** |
771 | STDMETHODIMP 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 | |
833 | ErrExit: |
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 | //***************************************************************************** |
848 | STDMETHODIMP 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 | |
952 | ErrExit: |
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 | //***************************************************************************** |
965 | STDMETHODIMP 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 | } |
1002 | ErrExit: |
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 | //***************************************************************************** |
1014 | STDMETHODIMP 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 | |
1049 | ErrExit: |
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 | //***************************************************************************** |
1060 | STDMETHODIMP |
1061 | RegMeta::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 | |
1096 | ErrExit: |
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 | //***************************************************************************** |
1108 | STDMETHODIMP 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 | |
1144 | ErrExit: |
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 | //***************************************************************************** |
1156 | STDMETHODIMP 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 | |
1228 | ErrExit: |
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 | //***************************************************************************** |
1239 | STDMETHODIMP 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 | |
1294 | ErrExit: |
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 | //***************************************************************************** |
1306 | STDMETHODIMP 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 | |
1400 | ErrExit: |
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 | //***************************************************************************** |
1415 | STDMETHODIMP 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 | |
1501 | ErrExit: |
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 | //***************************************************************************** |
1516 | STDMETHODIMP 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 | |
1616 | ErrExit: |
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 | //***************************************************************************** |
1629 | STDMETHODIMP 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 | |
1679 | ErrExit: |
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 | //***************************************************************************** |
1694 | STDMETHODIMP 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 | |
1737 | ErrExit: |
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 | //***************************************************************************** |
1750 | STDMETHODIMP 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 | |
1854 | ErrExit: |
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 | //***************************************************************************** |
1866 | STDMETHODIMP 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 | |
1901 | ErrExit: |
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 | //***************************************************************************** |
1913 | STDMETHODIMP |
1914 | RegMeta::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 | } |
1983 | ErrExit: |
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 | //***************************************************************************** |
1995 | STDMETHODIMP 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 | |
2030 | ErrExit: |
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 | //***************************************************************************** |
2050 | STDMETHODIMP 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 | |
2077 | ErrExit: |
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 | //******************************************************************************* |
2089 | STDMETHODIMP 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 | |
2119 | ErrExit: |
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 | //******************************************************************************* |
2132 | STDMETHODIMP 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 | |
2174 | ErrExit: |
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 | //******************************************************************************* |
2187 | STDMETHODIMP 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 | |
2213 | ErrExit: |
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 | |
2235 | STDMETHODIMP 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 | |
2271 | ErrExit: |
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 | //***************************************************************************** |
2285 | STDMETHODIMP 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 | |
2412 | ErrExit: |
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 | //***************************************************************************** |
2428 | STDMETHODIMP 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 | //***************************************************************************** |
2498 | STDMETHODIMP 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)); |
2537 | ErrExit: |
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 | //***************************************************************************** |
2547 | STDMETHODIMP 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 | |
2589 | ErrExit: |
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 | //***************************************************************************** |
2602 | STDMETHODIMP 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 | |
2644 | ErrExit: |
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 | //***************************************************************************** |
2657 | STDMETHODIMP 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 | |
2721 | ErrExit: |
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 | //***************************************************************************** |
2735 | STDMETHODIMP 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)); |
2754 | ErrExit: |
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 | //***************************************************************************** |
2765 | HRESULT 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 | } |
2827 | ErrExit: |
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 | //***************************************************************************** |
2837 | HRESULT 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 | |
2939 | ErrExit: |
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 | //***************************************************************************** |
2949 | HRESULT 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 | |
3107 | ErrExit: |
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 | //***************************************************************************** |
3119 | HRESULT 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 | |
3202 | ErrExit: |
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 | //***************************************************************************** |
3212 | HRESULT 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 | |
3261 | ErrExit: |
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 | //***************************************************************************** |
3271 | HRESULT 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 | |
3309 | ErrExit: |
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 | //***************************************************************************** |
3319 | HRESULT 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 | |
3364 | ErrExit: |
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 | //***************************************************************************** |
3375 | HRESULT 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 | //***************************************************************************** |
3407 | HRESULT 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 | |
3453 | ErrExit: |
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 | //***************************************************************************** |
3463 | HRESULT 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 | |
3503 | ErrExit: |
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 | //***************************************************************************** |
3513 | HRESULT 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 | |
3598 | ErrExit: |
3599 | END_ENTRYPOINT_NOTHROW; |
3600 | |
3601 | return hr; |
3602 | } // HRESULT RegMeta::GetNativeCallConvFromSig() |
3603 | |
3604 | //***************************************************************************** |
3605 | // Helper used by GetNativeCallingConvFromSig. |
3606 | //***************************************************************************** |
3607 | HRESULT 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 | |
3675 | ErrExit: |
3676 | |
3677 | return hr; |
3678 | } // HRESULT RegMeta::_CheckCmodForCallConv() |
3679 | |
3680 | //***************************************************************************** |
3681 | // Helper used by GetNativeCallingConvFromSig. |
3682 | //***************************************************************************** |
3683 | HRESULT 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 | |
3806 | ErrExit: |
3807 | |
3808 | return hr; |
3809 | } // HRESULT RegMeta::_SearchOneArgForCallConv() |
3810 | |