1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | // File: RegMeta_IMetaDataImport.cpp |
6 | // |
7 | |
8 | // |
9 | // Methods of code:RegMeta class which implement public API interfaces: |
10 | // * code:IMetaDataImport |
11 | // * code:IMetaDataImport2 |
12 | // |
13 | // ====================================================================================== |
14 | |
15 | #include "stdafx.h" |
16 | #include "regmeta.h" |
17 | #include "metadata.h" |
18 | #include "corerror.h" |
19 | #include "mdutil.h" |
20 | #include "rwutil.h" |
21 | #include "mdlog.h" |
22 | #include "importhelper.h" |
23 | #include "filtermanager.h" |
24 | #include "mdperf.h" |
25 | #include "switches.h" |
26 | #include "posterror.h" |
27 | #include "stgio.h" |
28 | #include "sstring.h" |
29 | |
30 | #include <metamodelrw.h> |
31 | |
32 | #define DEFINE_CUSTOM_NODUPCHECK 1 |
33 | #define DEFINE_CUSTOM_DUPCHECK 2 |
34 | #define SET_CUSTOM 3 |
35 | |
36 | #if defined(_DEBUG) && defined(_TRACE_REMAPS) |
37 | #define LOGGING |
38 | #endif |
39 | #include <log.h> |
40 | |
41 | #ifdef _MSC_VER |
42 | #pragma warning(disable: 4102) |
43 | #endif |
44 | |
45 | //***************************************************************************** |
46 | // determine if a token is valid or not |
47 | //***************************************************************************** |
48 | BOOL RegMeta::IsValidToken( // true if tk is valid token |
49 | mdToken tk) // [IN] token to be checked |
50 | { |
51 | BOOL fRet = FALSE; |
52 | HRESULT hr = S_OK; |
53 | BEGIN_ENTRYPOINT_VOIDRET; |
54 | |
55 | LOCKREADNORET(); |
56 | |
57 | // If acquiring the lock failed... |
58 | IfFailGo(hr); |
59 | |
60 | fRet = m_pStgdb->m_MiniMd._IsValidToken(tk); |
61 | |
62 | ErrExit: |
63 | END_ENTRYPOINT_VOIDRET; |
64 | return fRet; |
65 | } // RegMeta::IsValidToken |
66 | |
67 | //***************************************************************************** |
68 | // Close an enumerator. |
69 | //***************************************************************************** |
70 | void STDMETHODCALLTYPE RegMeta::CloseEnum( |
71 | HCORENUM hEnum) // The enumerator. |
72 | { |
73 | BEGIN_CLEANUP_ENTRYPOINT; |
74 | |
75 | LOG((LOGMD, "RegMeta::CloseEnum(0x%08x)\n" , hEnum)); |
76 | |
77 | // No need to lock this function. |
78 | HENUMInternal *pmdEnum = reinterpret_cast<HENUMInternal *> (hEnum); |
79 | |
80 | if (pmdEnum == NULL) |
81 | return; |
82 | |
83 | // This function may be called through RCW. When hosted, we have probed before this call, so the |
84 | // following contract violation is OK. |
85 | CONTRACT_VIOLATION(SOToleranceViolation); |
86 | HENUMInternal::DestroyEnum(pmdEnum); |
87 | END_CLEANUP_ENTRYPOINT; |
88 | } // RegMeta::CloseEnum |
89 | |
90 | //***************************************************************************** |
91 | // Query the count of items represented by an enumerator. |
92 | //***************************************************************************** |
93 | HRESULT CountEnum( |
94 | HCORENUM hEnum, // The enumerator. |
95 | ULONG *pulCount) // Put the count here. |
96 | { |
97 | HENUMInternal *pmdEnum = reinterpret_cast<HENUMInternal *> (hEnum); |
98 | HRESULT hr = S_OK; |
99 | |
100 | // No need to lock this function. |
101 | |
102 | LOG((LOGMD, "RegMeta::CountEnum(0x%08x, 0x%08x)\n" , hEnum, pulCount)); |
103 | START_MD_PERF(); |
104 | |
105 | _ASSERTE( pulCount ); |
106 | |
107 | if (pmdEnum == NULL) |
108 | { |
109 | *pulCount = 0; |
110 | goto ErrExit; |
111 | } |
112 | |
113 | if (pmdEnum->m_tkKind == (TBL_MethodImpl << 24)) |
114 | { |
115 | // Number of tokens must always be a multiple of 2. |
116 | _ASSERTE(! (pmdEnum->m_ulCount % 2) ); |
117 | // There are two entries in the Enumerator for each MethodImpl. |
118 | *pulCount = pmdEnum->m_ulCount / 2; |
119 | } |
120 | else |
121 | *pulCount = pmdEnum->m_ulCount; |
122 | ErrExit: |
123 | STOP_MD_PERF(CountEnum); |
124 | return hr; |
125 | } // ::CountEnum |
126 | |
127 | STDMETHODIMP RegMeta::CountEnum( |
128 | HCORENUM hEnum, // The enumerator. |
129 | ULONG *pulCount) // Put the count here. |
130 | { |
131 | HRESULT hr = S_OK; |
132 | BEGIN_ENTRYPOINT_NOTHROW; |
133 | |
134 | hr = ::CountEnum(hEnum, pulCount); |
135 | END_ENTRYPOINT_NOTHROW; |
136 | return hr; |
137 | } // RegMeta::CountEnum |
138 | |
139 | //***************************************************************************** |
140 | // Reset an enumerator to any position within the enumerator. |
141 | //***************************************************************************** |
142 | STDMETHODIMP RegMeta::ResetEnum( |
143 | HCORENUM hEnum, // The enumerator. |
144 | ULONG ulPos) // Seek position. |
145 | { |
146 | HRESULT hr = S_OK; |
147 | |
148 | BEGIN_ENTRYPOINT_NOTHROW; |
149 | |
150 | HENUMInternal *pmdEnum = reinterpret_cast<HENUMInternal *> (hEnum); |
151 | |
152 | // No need to lock this function. |
153 | |
154 | LOG((LOGMD, "RegMeta::ResetEnum(0x%08x, 0x%08x)\n" , hEnum, ulPos)); |
155 | START_MD_PERF(); |
156 | |
157 | if (pmdEnum == NULL) |
158 | goto ErrExit; |
159 | |
160 | pmdEnum->u.m_ulCur = pmdEnum->u.m_ulStart + ulPos; |
161 | |
162 | ErrExit: |
163 | STOP_MD_PERF(ResetEnum); |
164 | END_ENTRYPOINT_NOTHROW; |
165 | return hr; |
166 | } // RegMeta::ResetEnum |
167 | |
168 | //***************************************************************************** |
169 | // Enumerate Sym.TypeDef. |
170 | //***************************************************************************** |
171 | STDMETHODIMP RegMeta::EnumTypeDefs( |
172 | HCORENUM *phEnum, // Pointer to the enumerator. |
173 | mdTypeDef rTypeDefs[], // Put TypeDefs here. |
174 | ULONG cMax, // Max TypeDefs to put. |
175 | ULONG *pcTypeDefs) // Put # put here. |
176 | { |
177 | HRESULT hr = S_OK; |
178 | |
179 | BEGIN_ENTRYPOINT_NOTHROW; |
180 | |
181 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
182 | HENUMInternal *pEnum; |
183 | |
184 | LOG((LOGMD, "RegMeta::EnumTypeDefs(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
185 | phEnum, rTypeDefs, cMax, pcTypeDefs)); |
186 | START_MD_PERF(); |
187 | LOCKREAD(); |
188 | |
189 | |
190 | if ( *ppmdEnum == 0 ) |
191 | { |
192 | // instantiating a new ENUM |
193 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
194 | |
195 | if (pMiniMd->HasDelete() && |
196 | ((m_OptionValue.m_ImportOption & MDImportOptionAllTypeDefs) == 0)) |
197 | { |
198 | IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtTypeDef, &pEnum) ); |
199 | |
200 | // add all Types to the dynamic array if name is not _Delete |
201 | for (ULONG index = 2; index <= pMiniMd->getCountTypeDefs(); index ++ ) |
202 | { |
203 | TypeDefRec *pRec; |
204 | IfFailGo(pMiniMd->GetTypeDefRecord(index, &pRec)); |
205 | LPCSTR szTypeDefName; |
206 | IfFailGo(pMiniMd->getNameOfTypeDef(pRec, &szTypeDefName)); |
207 | if (IsDeletedName(szTypeDefName)) |
208 | { |
209 | continue; |
210 | } |
211 | IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtTypeDef) ) ); |
212 | } |
213 | } |
214 | else |
215 | { |
216 | // create the enumerator |
217 | IfFailGo( HENUMInternal::CreateSimpleEnum( |
218 | mdtTypeDef, |
219 | 2, |
220 | pMiniMd->getCountTypeDefs() + 1, |
221 | &pEnum) ); |
222 | } |
223 | |
224 | // set the output parameter |
225 | *ppmdEnum = pEnum; |
226 | } |
227 | else |
228 | { |
229 | pEnum = *ppmdEnum; |
230 | } |
231 | |
232 | // we can only fill the minimun of what caller asked for or what we have left |
233 | hr = HENUMInternal::EnumWithCount(pEnum, cMax, rTypeDefs, pcTypeDefs); |
234 | |
235 | ErrExit: |
236 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
237 | |
238 | STOP_MD_PERF(EnumTypeDefs); |
239 | |
240 | END_ENTRYPOINT_NOTHROW; |
241 | |
242 | return hr; |
243 | } // RegMeta::EnumTypeDefs |
244 | |
245 | //***************************************************************************** |
246 | // Enumerate Sym.InterfaceImpl where Coclass == td |
247 | //***************************************************************************** |
248 | STDMETHODIMP RegMeta::EnumInterfaceImpls( |
249 | HCORENUM *phEnum, // Pointer to the enum. |
250 | mdTypeDef td, // TypeDef to scope the enumeration. |
251 | mdInterfaceImpl rImpls[], // Put InterfaceImpls here. |
252 | ULONG cMax, // Max InterfaceImpls to put. |
253 | ULONG *pcImpls) // Put # put here. |
254 | { |
255 | HRESULT hr = S_OK; |
256 | |
257 | BEGIN_ENTRYPOINT_NOTHROW; |
258 | |
259 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
260 | ULONG ridStart; |
261 | ULONG ridEnd; |
262 | HENUMInternal *pEnum; |
263 | InterfaceImplRec *pRec; |
264 | ULONG index; |
265 | |
266 | LOG((LOGMD, "RegMeta::EnumInterfaceImpls(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
267 | phEnum, td, rImpls, cMax, pcImpls)); |
268 | START_MD_PERF(); |
269 | LOCKREAD(); |
270 | |
271 | _ASSERTE(TypeFromToken(td) == mdtTypeDef); |
272 | |
273 | |
274 | if ( *ppmdEnum == 0 ) |
275 | { |
276 | // instantiating a new ENUM |
277 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
278 | if ( pMiniMd->IsSorted( TBL_InterfaceImpl ) ) |
279 | { |
280 | IfFailGo(pMiniMd->getInterfaceImplsForTypeDef(RidFromToken(td), &ridEnd, &ridStart)); |
281 | IfFailGo( HENUMInternal::CreateSimpleEnum( mdtInterfaceImpl, ridStart, ridEnd, &pEnum) ); |
282 | } |
283 | else |
284 | { |
285 | // table is not sorted so we have to create dynmaic array |
286 | // create the dynamic enumerator |
287 | // |
288 | ridStart = 1; |
289 | ridEnd = pMiniMd->getCountInterfaceImpls() + 1; |
290 | |
291 | IfFailGo( HENUMInternal::CreateDynamicArrayEnum( mdtInterfaceImpl, &pEnum) ); |
292 | |
293 | for (index = ridStart; index < ridEnd; index ++ ) |
294 | { |
295 | IfFailGo(pMiniMd->GetInterfaceImplRecord(index, &pRec)); |
296 | if ( td == pMiniMd->getClassOfInterfaceImpl(pRec) ) |
297 | { |
298 | IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtInterfaceImpl) ) ); |
299 | } |
300 | } |
301 | } |
302 | |
303 | // set the output parameter |
304 | *ppmdEnum = pEnum; |
305 | } |
306 | else |
307 | { |
308 | pEnum = *ppmdEnum; |
309 | } |
310 | |
311 | // fill the output token buffer |
312 | hr = HENUMInternal::EnumWithCount(pEnum, cMax, rImpls, pcImpls); |
313 | |
314 | ErrExit: |
315 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
316 | |
317 | STOP_MD_PERF(EnumInterfaceImpls); |
318 | |
319 | END_ENTRYPOINT_NOTHROW; |
320 | |
321 | return hr; |
322 | } // RegMeta::EnumInterfaceImpls |
323 | |
324 | STDMETHODIMP RegMeta::EnumGenericParams(HCORENUM *phEnum, mdToken tkOwner, |
325 | mdGenericParam rTokens[], ULONG cMaxTokens, ULONG *pcTokens) |
326 | { |
327 | HRESULT hr = S_OK; |
328 | |
329 | BEGIN_ENTRYPOINT_NOTHROW; |
330 | |
331 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
332 | ULONG ridStart; |
333 | ULONG ridEnd; |
334 | HENUMInternal *pEnum; |
335 | GenericParamRec *pRec; |
336 | ULONG index; |
337 | CMiniMdRW *pMiniMd = NULL; |
338 | |
339 | |
340 | LOG((LOGMD, "RegMeta::EnumGenericParams(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
341 | phEnum, tkOwner, rTokens, cMaxTokens, pcTokens)); |
342 | START_MD_PERF(); |
343 | LOCKREAD(); |
344 | |
345 | pMiniMd = &(m_pStgdb->m_MiniMd); |
346 | |
347 | |
348 | // See if this version of the metadata can do Generics |
349 | if (!pMiniMd->SupportsGenerics()) |
350 | { |
351 | if (pcTokens) |
352 | *pcTokens = 0; |
353 | hr = S_FALSE; |
354 | goto ErrExit; |
355 | } |
356 | |
357 | |
358 | _ASSERTE(TypeFromToken(tkOwner) == mdtTypeDef || TypeFromToken(tkOwner) == mdtMethodDef); |
359 | |
360 | |
361 | if ( *ppmdEnum == 0 ) |
362 | { |
363 | // instantiating a new ENUM |
364 | |
365 | //@todo GENERICS: review this. Are we expecting a sorted table or not? |
366 | if ( pMiniMd->IsSorted( TBL_GenericParam ) ) |
367 | { |
368 | if (TypeFromToken(tkOwner) == mdtTypeDef) |
369 | { |
370 | IfFailGo(pMiniMd->getGenericParamsForTypeDef(RidFromToken(tkOwner), &ridEnd, &ridStart)); |
371 | } |
372 | else |
373 | { |
374 | IfFailGo(pMiniMd->getGenericParamsForMethodDef(RidFromToken(tkOwner), &ridEnd, &ridStart)); |
375 | } |
376 | |
377 | IfFailGo( HENUMInternal::CreateSimpleEnum(mdtGenericParam, ridStart, ridEnd, &pEnum) ); |
378 | } |
379 | else |
380 | { |
381 | // table is not sorted so we have to create dynamic array |
382 | // create the dynamic enumerator |
383 | // |
384 | ridStart = 1; |
385 | ridEnd = pMiniMd->getCountGenericParams() + 1; |
386 | |
387 | IfFailGo( HENUMInternal::CreateDynamicArrayEnum(mdtGenericParam, &pEnum) ); |
388 | |
389 | for (index = ridStart; index < ridEnd; index ++ ) |
390 | { |
391 | IfFailGo(pMiniMd->GetGenericParamRecord(index, &pRec)); |
392 | if ( tkOwner == pMiniMd->getOwnerOfGenericParam(pRec) ) |
393 | { |
394 | IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtGenericParam) ) ); |
395 | } |
396 | } |
397 | } |
398 | |
399 | // set the output parameter |
400 | *ppmdEnum = pEnum; |
401 | } |
402 | else |
403 | { |
404 | pEnum = *ppmdEnum; |
405 | } |
406 | |
407 | // fill the output token buffer |
408 | hr = HENUMInternal::EnumWithCount(pEnum, cMaxTokens, rTokens, pcTokens); |
409 | |
410 | ErrExit: |
411 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
412 | STOP_MD_PERF(EnumGenericPars); |
413 | END_ENTRYPOINT_NOTHROW; |
414 | |
415 | return hr; |
416 | } // RegMeta::EnumGenericParams |
417 | |
418 | STDMETHODIMP RegMeta::EnumMethodSpecs( |
419 | HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. |
420 | mdToken tkOwner, // [IN] MethodDef or MemberRef whose MethodSpecs are requested |
421 | mdMethodSpec rTokens[], // [OUT] Put MethodSpecs here. |
422 | ULONG cMaxTokens, // [IN] Max tokens to put. |
423 | ULONG *pcTokens) // [OUT] Put actual count here. |
424 | { |
425 | HRESULT hr = S_OK; |
426 | |
427 | BEGIN_ENTRYPOINT_NOTHROW; |
428 | |
429 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
430 | ULONG ridStart; |
431 | ULONG ridEnd; |
432 | HENUMInternal *pEnum; |
433 | MethodSpecRec *pRec; |
434 | ULONG index; |
435 | CMiniMdRW *pMiniMd = NULL; |
436 | |
437 | LOG((LOGMD, "RegMeta::EnumMethodSpecs(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
438 | phEnum, tkOwner, rTokens, cMaxTokens, pcTokens)); |
439 | START_MD_PERF(); |
440 | LOCKREAD(); |
441 | |
442 | pMiniMd = &(m_pStgdb->m_MiniMd); |
443 | |
444 | // See if this version of the metadata can do Generics |
445 | if (!pMiniMd->SupportsGenerics()) |
446 | { |
447 | if (pcTokens) |
448 | *pcTokens = 0; |
449 | hr = S_FALSE; |
450 | goto ErrExit; |
451 | } |
452 | |
453 | |
454 | _ASSERTE(RidFromToken(tkOwner)==0 || TypeFromToken(tkOwner) == mdtMethodDef || TypeFromToken(tkOwner) == mdtMemberRef); |
455 | |
456 | |
457 | if ( *ppmdEnum == 0 ) |
458 | { |
459 | // instantiating a new ENUM |
460 | |
461 | if(RidFromToken(tkOwner)==0) // enumerate all MethodSpecs |
462 | { |
463 | ridStart = 1; |
464 | ridEnd = pMiniMd->getCountMethodSpecs() + 1; |
465 | |
466 | IfFailGo( HENUMInternal::CreateSimpleEnum( mdtMethodSpec, ridStart, ridEnd, &pEnum) ); |
467 | } |
468 | else |
469 | { |
470 | //@todo GENERICS: review this. Are we expecting a sorted table or not? |
471 | if ( pMiniMd->IsSorted( TBL_MethodSpec ) ) |
472 | { |
473 | if (TypeFromToken(tkOwner) == mdtMemberRef) |
474 | { |
475 | IfFailGo(pMiniMd->getMethodSpecsForMemberRef(RidFromToken(tkOwner), &ridEnd, &ridStart)); |
476 | } |
477 | else |
478 | { |
479 | IfFailGo(pMiniMd->getMethodSpecsForMethodDef(RidFromToken(tkOwner), &ridEnd, &ridStart)); |
480 | } |
481 | |
482 | IfFailGo( HENUMInternal::CreateSimpleEnum(mdtMethodSpec, ridStart, ridEnd, &pEnum) ); |
483 | } |
484 | else |
485 | { |
486 | // table is not sorted so we have to create dynamic array |
487 | // create the dynamic enumerator |
488 | // |
489 | ridStart = 1; |
490 | ridEnd = pMiniMd->getCountMethodSpecs() + 1; |
491 | |
492 | IfFailGo( HENUMInternal::CreateDynamicArrayEnum(mdtMethodSpec, &pEnum) ); |
493 | |
494 | for (index = ridStart; index < ridEnd; index ++ ) |
495 | { |
496 | IfFailGo(pMiniMd->GetMethodSpecRecord(index, &pRec)); |
497 | if ( tkOwner == pMiniMd->getMethodOfMethodSpec(pRec) ) |
498 | { |
499 | IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, mdtMethodSpec) ) ); |
500 | } |
501 | } |
502 | } |
503 | } |
504 | // set the output parameter |
505 | *ppmdEnum = pEnum; |
506 | } |
507 | else |
508 | { |
509 | pEnum = *ppmdEnum; |
510 | } |
511 | |
512 | // fill the output token buffer |
513 | hr = HENUMInternal::EnumWithCount(pEnum, cMaxTokens, rTokens, pcTokens); |
514 | |
515 | ErrExit: |
516 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
517 | STOP_MD_PERF(EnumMethodSpecs); |
518 | END_ENTRYPOINT_NOTHROW; |
519 | |
520 | return hr; |
521 | } // STDMETHODIMP RegMeta::EnumMethodSpecs() |
522 | |
523 | STDMETHODIMP RegMeta::EnumGenericParamConstraints( |
524 | HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. |
525 | mdGenericParam tkOwner, // [IN] GenericParam whose constraints are requested |
526 | mdGenericParamConstraint rTokens[], // [OUT] Put GenericParamConstraints here. |
527 | ULONG cMaxTokens, // [IN] Max GenericParamConstraints to put. |
528 | ULONG *pcTokens) // [OUT] Put # of tokens here. |
529 | { |
530 | HRESULT hr = S_OK; |
531 | |
532 | BEGIN_ENTRYPOINT_NOTHROW; |
533 | |
534 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
535 | ULONG ridStart; |
536 | ULONG ridEnd; |
537 | HENUMInternal *pEnum; |
538 | GenericParamConstraintRec *pRec; |
539 | ULONG index; |
540 | CMiniMdRW *pMiniMd = NULL; |
541 | |
542 | LOG((LOGMD, "RegMeta::EnumGenericParamConstraints(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
543 | phEnum, tkOwner, rTokens, cMaxTokens, pcTokens)); |
544 | START_MD_PERF(); |
545 | LOCKREAD(); |
546 | |
547 | pMiniMd = &(m_pStgdb->m_MiniMd); |
548 | |
549 | |
550 | if(TypeFromToken(tkOwner) != mdtGenericParam) |
551 | IfFailGo(META_E_BAD_INPUT_PARAMETER); |
552 | |
553 | // See if this version of the metadata can do Generics |
554 | if (!pMiniMd->SupportsGenerics()) |
555 | { |
556 | if (pcTokens) |
557 | *pcTokens = 0; |
558 | hr = S_FALSE; |
559 | goto ErrExit; |
560 | } |
561 | |
562 | if ( *ppmdEnum == 0 ) |
563 | { |
564 | // instantiating a new ENUM |
565 | |
566 | //<TODO> GENERICS: review this. Are we expecting a sorted table or not? </TODO> |
567 | if ( pMiniMd->IsSorted( TBL_GenericParamConstraint ) ) |
568 | { |
569 | IfFailGo(pMiniMd->getGenericParamConstraintsForGenericParam(RidFromToken(tkOwner), &ridEnd, &ridStart)); |
570 | IfFailGo( HENUMInternal::CreateSimpleEnum(mdtGenericParamConstraint, ridStart, ridEnd, &pEnum) ); |
571 | } |
572 | else |
573 | { |
574 | // table is not sorted so we have to create dynamic array |
575 | // create the dynamic enumerator |
576 | // |
577 | ridStart = 1; |
578 | ridEnd = pMiniMd->getCountGenericParamConstraints() + 1; |
579 | |
580 | IfFailGo( HENUMInternal::CreateDynamicArrayEnum(mdtGenericParamConstraint, &pEnum)); |
581 | |
582 | for (index = ridStart; index < ridEnd; index ++ ) |
583 | { |
584 | IfFailGo(pMiniMd->GetGenericParamConstraintRecord(index, &pRec)); |
585 | if ( tkOwner == pMiniMd->getOwnerOfGenericParamConstraint(pRec)) |
586 | { |
587 | IfFailGo( HENUMInternal::AddElementToEnum(pEnum, TokenFromRid(index, |
588 | mdtGenericParamConstraint))); |
589 | } |
590 | } |
591 | } |
592 | |
593 | // set the output parameter |
594 | *ppmdEnum = pEnum; |
595 | } |
596 | else |
597 | { |
598 | pEnum = *ppmdEnum; |
599 | } |
600 | |
601 | // fill the output token buffer |
602 | hr = HENUMInternal::EnumWithCount(pEnum, cMaxTokens, rTokens, pcTokens); |
603 | |
604 | ErrExit: |
605 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
606 | STOP_MD_PERF(EnumGenericParamConstraints); |
607 | END_ENTRYPOINT_NOTHROW; |
608 | |
609 | return hr; |
610 | } |
611 | |
612 | //***************************************************************************** |
613 | // Enumerate Sym.TypeRef |
614 | //***************************************************************************** |
615 | STDMETHODIMP RegMeta::EnumTypeRefs( |
616 | HCORENUM *phEnum, // Pointer to the enumerator. |
617 | mdTypeRef rTypeRefs[], // Put TypeRefs here. |
618 | ULONG cMax, // Max TypeRefs to put. |
619 | ULONG *pcTypeRefs) // Put # put here. |
620 | { |
621 | HRESULT hr = S_OK; |
622 | |
623 | BEGIN_ENTRYPOINT_NOTHROW; |
624 | |
625 | HENUMInternal **ppmdEnum = reinterpret_cast<HENUMInternal **> (phEnum); |
626 | ULONG cTotal; |
627 | HENUMInternal *pEnum = *ppmdEnum; |
628 | |
629 | |
630 | |
631 | LOG((LOGMD, "RegMeta::EnumTypeRefs(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
632 | phEnum, rTypeRefs, cMax, pcTypeRefs)); |
633 | START_MD_PERF(); |
634 | LOCKREAD(); |
635 | |
636 | if ( pEnum == 0 ) |
637 | { |
638 | // instantiating a new ENUM |
639 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
640 | cTotal = pMiniMd->getCountTypeRefs(); |
641 | |
642 | IfFailGo( HENUMInternal::CreateSimpleEnum( mdtTypeRef, 1, cTotal + 1, &pEnum) ); |
643 | |
644 | // set the output parameter |
645 | *ppmdEnum = pEnum; |
646 | } |
647 | |
648 | // fill the output token buffer |
649 | hr = HENUMInternal::EnumWithCount(pEnum, cMax, rTypeRefs, pcTypeRefs); |
650 | |
651 | ErrExit: |
652 | HENUMInternal::DestroyEnumIfEmpty(ppmdEnum); |
653 | |
654 | |
655 | STOP_MD_PERF(EnumTypeRefs); |
656 | END_ENTRYPOINT_NOTHROW; |
657 | |
658 | return hr; |
659 | } // STDMETHODIMP RegMeta::EnumTypeRefs() |
660 | |
661 | //***************************************************************************** |
662 | // Given a namespace and a class name, return the typedef |
663 | //***************************************************************************** |
664 | STDMETHODIMP RegMeta::FindTypeDefByName(// S_OK or error. |
665 | LPCWSTR wzTypeDef, // [IN] Name of the Type. |
666 | mdToken tkEnclosingClass, // [IN] Enclosing class. |
667 | mdTypeDef *ptd) // [OUT] Put the TypeDef token here. |
668 | { |
669 | HRESULT hr = S_OK; |
670 | BEGIN_ENTRYPOINT_NOTHROW |
671 | |
672 | LOG((LOGMD, "{%08x} RegMeta::FindTypeDefByName(%S, 0x%08x, 0x%08x)\n" , |
673 | this, MDSTR(wzTypeDef), tkEnclosingClass, ptd)); |
674 | START_MD_PERF(); |
675 | LOCKREAD(); |
676 | |
677 | |
678 | if (wzTypeDef == NULL) |
679 | IfFailGo(E_INVALIDARG); |
680 | PREFIX_ASSUME(wzTypeDef != NULL); |
681 | LPSTR szTypeDef; |
682 | UTF8STR(wzTypeDef, szTypeDef); |
683 | LPCSTR szNamespace; |
684 | LPCSTR szName; |
685 | |
686 | _ASSERTE(ptd); |
687 | _ASSERTE(TypeFromToken(tkEnclosingClass) == mdtTypeDef || |
688 | TypeFromToken(tkEnclosingClass) == mdtTypeRef || |
689 | IsNilToken(tkEnclosingClass)); |
690 | |
691 | // initialize output parameter |
692 | *ptd = mdTypeDefNil; |
693 | |
694 | ns::SplitInline(szTypeDef, szNamespace, szName); |
695 | hr = ImportHelper::FindTypeDefByName(&(m_pStgdb->m_MiniMd), |
696 | szNamespace, |
697 | szName, |
698 | tkEnclosingClass, |
699 | ptd); |
700 | ErrExit: |
701 | |
702 | STOP_MD_PERF(FindTypeDefByName); |
703 | END_ENTRYPOINT_NOTHROW; |
704 | |
705 | return hr; |
706 | } // STDMETHODIMP RegMeta::FindTypeDefByName() |
707 | |
708 | //***************************************************************************** |
709 | // Get values from Sym.Module |
710 | //***************************************************************************** |
711 | STDMETHODIMP RegMeta::GetScopeProps( |
712 | __out_ecount_opt (cchName) LPWSTR szName, // Put name here |
713 | ULONG cchName, // Size in chars of name buffer |
714 | ULONG *pchName, // Put actual length of name here |
715 | GUID *pmvid) // Put MVID here |
716 | { |
717 | HRESULT hr = S_OK; |
718 | |
719 | BEGIN_ENTRYPOINT_NOTHROW; |
720 | |
721 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
722 | ModuleRec *pModuleRec; |
723 | |
724 | |
725 | LOG((LOGMD, "RegMeta::GetScopeProps(%S, 0x%08x, 0x%08x, 0x%08x)\n" , |
726 | MDSTR(szName), cchName, pchName, pmvid)); |
727 | START_MD_PERF(); |
728 | LOCKREAD(); |
729 | |
730 | // there is only one module record |
731 | IfFailGo(pMiniMd->GetModuleRecord(1, &pModuleRec)); |
732 | |
733 | if (pmvid != NULL) |
734 | { |
735 | IfFailGo(pMiniMd->getMvidOfModule(pModuleRec, pmvid)); |
736 | } |
737 | // This call has to be last to set 'hr', so CLDB_S_TRUNCATION is not rewritten with S_OK |
738 | if (szName || pchName) |
739 | IfFailGo( pMiniMd->getNameOfModule(pModuleRec, szName, cchName, pchName) ); |
740 | ErrExit: |
741 | |
742 | STOP_MD_PERF(GetScopeProps); |
743 | END_ENTRYPOINT_NOTHROW; |
744 | |
745 | return hr; |
746 | } // STDMETHODIMP RegMeta::GetScopeProps() |
747 | |
748 | //***************************************************************************** |
749 | // Get the token for a Scope's (primary) module record. |
750 | //***************************************************************************** |
751 | STDMETHODIMP RegMeta::GetModuleFromScope(// S_OK. |
752 | mdModule *pmd) // [OUT] Put mdModule token here. |
753 | { |
754 | HRESULT hr = S_OK; |
755 | BEGIN_ENTRYPOINT_NOTHROW; |
756 | |
757 | LOG((LOGMD, "RegMeta::GetModuleFromScope(0x%08x)\n" , pmd)); |
758 | START_MD_PERF(); |
759 | |
760 | _ASSERTE(pmd); |
761 | |
762 | // No need to lock this function. |
763 | |
764 | *pmd = TokenFromRid(1, mdtModule); |
765 | |
766 | STOP_MD_PERF(GetModuleFromScope); |
767 | END_ENTRYPOINT_NOTHROW; |
768 | |
769 | return hr; |
770 | } // STDMETHODIMP RegMeta::GetModuleFromScope() |
771 | |
772 | //***************************************************************************** |
773 | // Given a token, is it (or its parent) global? |
774 | //***************************************************************************** |
775 | HRESULT RegMeta::IsGlobal( // S_OK ir error. |
776 | mdToken tk, // [IN] Type, Field, or Method token. |
777 | int *pbGlobal) // [OUT] Put 1 if global, 0 otherwise. |
778 | { |
779 | HRESULT hr=S_OK; // A result. |
780 | |
781 | BEGIN_ENTRYPOINT_NOTHROW; |
782 | |
783 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
784 | mdToken tkParent; // Parent of field or method. |
785 | |
786 | LOG((LOGMD, "RegMeta::GetTokenForGlobalType(0x%08x, %08x)\n" , tk, pbGlobal)); |
787 | //START_MD_PERF(); |
788 | |
789 | // No need to lock this function. |
790 | |
791 | if (!IsValidToken(tk)) |
792 | IfFailGo(E_INVALIDARG); |
793 | |
794 | switch (TypeFromToken(tk)) |
795 | { |
796 | case mdtTypeDef: |
797 | *pbGlobal = IsGlobalMethodParentToken(tk); |
798 | break; |
799 | |
800 | case mdtFieldDef: |
801 | IfFailGo( pMiniMd->FindParentOfFieldHelper(tk, &tkParent) ); |
802 | *pbGlobal = IsGlobalMethodParentToken(tkParent); |
803 | break; |
804 | |
805 | case mdtMethodDef: |
806 | IfFailGo( pMiniMd->FindParentOfMethodHelper(tk, &tkParent) ); |
807 | *pbGlobal = IsGlobalMethodParentToken(tkParent); |
808 | break; |
809 | |
810 | case mdtProperty: |
811 | IfFailGo( pMiniMd->FindParentOfPropertyHelper(tk, &tkParent) ); |
812 | *pbGlobal = IsGlobalMethodParentToken(tkParent); |
813 | break; |
814 | |
815 | case mdtEvent: |
816 | IfFailGo( pMiniMd->FindParentOfEventHelper(tk, &tkParent) ); |
817 | *pbGlobal = IsGlobalMethodParentToken(tkParent); |
818 | break; |
819 | |
820 | // Anything else is NOT global. |
821 | default: |
822 | *pbGlobal = FALSE; |
823 | } |
824 | |
825 | ErrExit: |
826 | //STOP_MD_PERF(GetModuleFromScope); |
827 | END_ENTRYPOINT_NOTHROW; |
828 | |
829 | return hr; |
830 | } // HRESULT RegMeta::IsGlobal() |
831 | |
832 | //***************************************************************************** |
833 | // return flags for a given class |
834 | //***************************************************************************** |
835 | HRESULT |
836 | RegMeta::GetTypeDefProps( |
837 | mdTypeDef td, // [IN] TypeDef token for inquiry. |
838 | __out_ecount_opt (cchTypeDef) LPWSTR szTypeDef, // [OUT] Put name here. |
839 | ULONG cchTypeDef, // [IN] size of name buffer in wide chars. |
840 | ULONG *pchTypeDef, // [OUT] put size of name (wide chars) here. |
841 | DWORD *pdwTypeDefFlags, // [OUT] Put flags here. |
842 | mdToken *ptkExtends) // [OUT] Put base class TypeDef/TypeRef here. |
843 | { |
844 | HRESULT hr = S_OK; |
845 | |
846 | BEGIN_ENTRYPOINT_NOTHROW; |
847 | |
848 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
849 | TypeDefRec *pTypeDefRec; |
850 | BOOL fTruncation = FALSE; // Was there name truncation? |
851 | |
852 | LOG((LOGMD, "{%08x} RegMeta::GetTypeDefProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
853 | this, td, szTypeDef, cchTypeDef, pchTypeDef, |
854 | pdwTypeDefFlags, ptkExtends)); |
855 | START_MD_PERF(); |
856 | LOCKREAD(); |
857 | |
858 | if (TypeFromToken(td) != mdtTypeDef) |
859 | { |
860 | hr = S_FALSE; |
861 | goto ErrExit; |
862 | } |
863 | if (td == mdTypeDefNil) |
864 | { // Backward compatibility with CLR 2.0 implementation |
865 | if (pdwTypeDefFlags != NULL) |
866 | *pdwTypeDefFlags = 0; |
867 | if (ptkExtends != NULL) |
868 | *ptkExtends = mdTypeRefNil; |
869 | if (pchTypeDef != NULL) |
870 | *pchTypeDef = 1; |
871 | if ((szTypeDef != NULL) && (cchTypeDef > 0)) |
872 | szTypeDef[0] = 0; |
873 | |
874 | hr = S_OK; |
875 | goto ErrExit; |
876 | } |
877 | |
878 | IfFailGo(pMiniMd->GetTypeDefRecord(RidFromToken(td), &pTypeDefRec)); |
879 | |
880 | if ((szTypeDef != NULL) || (pchTypeDef != NULL)) |
881 | { |
882 | LPCSTR szNamespace; |
883 | LPCSTR szName; |
884 | |
885 | IfFailGo(pMiniMd->getNamespaceOfTypeDef(pTypeDefRec, &szNamespace)); |
886 | MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzNamespace, szNamespace); |
887 | IfNullGo(wzNamespace); |
888 | |
889 | IfFailGo(pMiniMd->getNameOfTypeDef(pTypeDefRec, &szName)); |
890 | MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzName, szName); |
891 | IfNullGo(wzName); |
892 | |
893 | if (szTypeDef != NULL) |
894 | { |
895 | fTruncation = !(ns::MakePath(szTypeDef, cchTypeDef, wzNamespace, wzName)); |
896 | } |
897 | if (pchTypeDef != NULL) |
898 | { |
899 | if (fTruncation || (szTypeDef == NULL)) |
900 | { |
901 | *pchTypeDef = ns::GetFullLength(wzNamespace, wzName); |
902 | } |
903 | else |
904 | { |
905 | *pchTypeDef = (ULONG)(wcslen(szTypeDef) + 1); |
906 | } |
907 | } |
908 | } |
909 | if (pdwTypeDefFlags != NULL) |
910 | { // caller wants type flags |
911 | *pdwTypeDefFlags = pMiniMd->getFlagsOfTypeDef(pTypeDefRec); |
912 | } |
913 | if (ptkExtends != NULL) |
914 | { |
915 | *ptkExtends = pMiniMd->getExtendsOfTypeDef(pTypeDefRec); |
916 | |
917 | // take care of the 0 case |
918 | if (RidFromToken(*ptkExtends) == 0) |
919 | { |
920 | *ptkExtends = mdTypeRefNil; |
921 | } |
922 | } |
923 | |
924 | if (fTruncation && (hr == S_OK)) |
925 | { |
926 | if ((szTypeDef != NULL) && (cchTypeDef > 0)) |
927 | { // null-terminate the truncated output string |
928 | szTypeDef[cchTypeDef - 1] = W('\0'); |
929 | } |
930 | hr = CLDB_S_TRUNCATION; |
931 | } |
932 | |
933 | ErrExit: |
934 | END_ENTRYPOINT_NOTHROW; |
935 | |
936 | STOP_MD_PERF(GetTypeDefProps); |
937 | |
938 | return hr; |
939 | } // RegMeta::GetTypeDefProps |
940 | |
941 | //***************************************************************************** |
942 | // Retrieve information about an implemented interface. |
943 | //***************************************************************************** |
944 | STDMETHODIMP RegMeta::GetInterfaceImplProps( // S_OK or error. |
945 | mdInterfaceImpl iiImpl, // [IN] InterfaceImpl token. |
946 | mdTypeDef *pClass, // [OUT] Put implementing class token here. |
947 | mdToken *ptkIface) // [OUT] Put implemented interface token here. |
948 | { |
949 | HRESULT hr = S_OK; |
950 | |
951 | BEGIN_ENTRYPOINT_NOTHROW; |
952 | |
953 | CMiniMdRW *pMiniMd = NULL; |
954 | InterfaceImplRec *pIIRec = NULL; |
955 | |
956 | |
957 | |
958 | LOG((LOGMD, "RegMeta::GetInterfaceImplProps(0x%08x, 0x%08x, 0x%08x)\n" , |
959 | iiImpl, pClass, ptkIface)); |
960 | START_MD_PERF(); |
961 | LOCKREAD(); |
962 | |
963 | _ASSERTE(TypeFromToken(iiImpl) == mdtInterfaceImpl); |
964 | |
965 | pMiniMd = &(m_pStgdb->m_MiniMd); |
966 | IfFailGo(pMiniMd->GetInterfaceImplRecord(RidFromToken(iiImpl), &pIIRec)); |
967 | |
968 | if (pClass) |
969 | { |
970 | *pClass = pMiniMd->getClassOfInterfaceImpl(pIIRec); |
971 | } |
972 | if (ptkIface) |
973 | { |
974 | *ptkIface = pMiniMd->getInterfaceOfInterfaceImpl(pIIRec); |
975 | } |
976 | |
977 | ErrExit: |
978 | STOP_MD_PERF(GetInterfaceImplProps); |
979 | END_ENTRYPOINT_NOTHROW; |
980 | |
981 | return hr; |
982 | } // STDMETHODIMP RegMeta::GetInterfaceImplProps() |
983 | |
984 | //***************************************************************************** |
985 | // Retrieve information about a TypeRef. |
986 | //***************************************************************************** |
987 | STDMETHODIMP |
988 | RegMeta::GetTypeRefProps( |
989 | mdTypeRef tr, // The class ref token. |
990 | mdToken *ptkResolutionScope, // Resolution scope, ModuleRef or AssemblyRef. |
991 | __out_ecount_opt (cchTypeRef) LPWSTR szTypeRef, // Put the name here. |
992 | ULONG cchTypeRef, // Size of the name buffer, wide chars. |
993 | ULONG *pchTypeRef) // Put actual size of name here. |
994 | { |
995 | HRESULT hr = S_OK; |
996 | |
997 | BEGIN_ENTRYPOINT_NOTHROW; |
998 | |
999 | CMiniMdRW *pMiniMd; |
1000 | TypeRefRec *pTypeRefRec; |
1001 | BOOL fTruncation = FALSE; // Was there name truncation? |
1002 | |
1003 | LOG((LOGMD, "RegMeta::GetTypeRefProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n" , |
1004 | tr, ptkResolutionScope, szTypeRef, cchTypeRef, pchTypeRef)); |
1005 | |
1006 | START_MD_PERF(); |
1007 | LOCKREAD(); |
1008 | |
1009 | if (TypeFromToken(tr) != mdtTypeRef) |
1010 | { |
1011 | hr = S_FALSE; |
1012 | goto ErrExit; |
1013 | } |
1014 | if (tr == mdTypeRefNil) |
1015 | { // Backward compatibility with CLR 2.0 implementation |
1016 | if (ptkResolutionScope != NULL) |
1017 | *ptkResolutionScope = mdTokenNil; |
1018 | if (pchTypeRef != NULL) |
1019 | *pchTypeRef = 1; |
1020 | if ((szTypeRef != NULL) && (cchTypeRef > 0)) |
1021 | szTypeRef[0] = 0; |
1022 | |
1023 | hr = S_OK; |
1024 | goto ErrExit; |
1025 | } |
1026 | |
1027 | pMiniMd = &(m_pStgdb->m_MiniMd); |
1028 | IfFailGo(pMiniMd->GetTypeRefRecord(RidFromToken(tr), &pTypeRefRec)); |
1029 | |
1030 | if (ptkResolutionScope != NULL) |
1031 | { |
1032 | *ptkResolutionScope = pMiniMd->getResolutionScopeOfTypeRef(pTypeRefRec); |
1033 | } |
1034 | |
1035 | if ((szTypeRef != NULL) || (pchTypeRef != NULL)) |
1036 | { |
1037 | LPCSTR szNamespace; |
1038 | LPCSTR szName; |
1039 | |
1040 | IfFailGo(pMiniMd->getNamespaceOfTypeRef(pTypeRefRec, &szNamespace)); |
1041 | MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzNamespace, szNamespace); |
1042 | IfNullGo(wzNamespace); |
1043 | |
1044 | IfFailGo(pMiniMd->getNameOfTypeRef(pTypeRefRec, &szName)); |
1045 | MAKE_WIDEPTR_FROMUTF8_NOTHROW(wzName, szName); |
1046 | IfNullGo(wzName); |
1047 | |
1048 | if (szTypeRef != NULL) |
1049 | { |
1050 | fTruncation = !(ns::MakePath(szTypeRef, cchTypeRef, wzNamespace, wzName)); |
1051 | } |
1052 | if (pchTypeRef != NULL) |
1053 | { |
1054 | if (fTruncation || (szTypeRef == NULL)) |
1055 | { |
1056 | *pchTypeRef = ns::GetFullLength(wzNamespace, wzName); |
1057 | } |
1058 | else |
1059 | { |
1060 | *pchTypeRef = (ULONG)(wcslen(szTypeRef) + 1); |
1061 | } |
1062 | } |
1063 | } |
1064 | if (fTruncation && (hr == S_OK)) |
1065 | { |
1066 | if ((szTypeRef != NULL) && (cchTypeRef > 0)) |
1067 | { // null-terminate the truncated output string |
1068 | szTypeRef[cchTypeRef - 1] = W('\0'); |
1069 | } |
1070 | hr = CLDB_S_TRUNCATION; |
1071 | } |
1072 | |
1073 | ErrExit: |
1074 | STOP_MD_PERF(GetTypeRefProps); |
1075 | END_ENTRYPOINT_NOTHROW; |
1076 | return hr; |
1077 | } // RegMeta::GetTypeRefProps |
1078 | |
1079 | //***************************************************************************** |
1080 | // Given a TypeRef name, return the typeref |
1081 | //***************************************************************************** |
1082 | STDMETHODIMP RegMeta::FindTypeRef( // S_OK or error. |
1083 | mdToken tkResolutionScope, // [IN] Resolution Scope. |
1084 | LPCWSTR wzTypeName, // [IN] Name of the TypeRef. |
1085 | mdTypeRef *ptk) // [OUT] Put the TypeRef token here. |
1086 | { |
1087 | HRESULT hr = S_OK; // A result. |
1088 | |
1089 | BEGIN_ENTRYPOINT_NOTHROW; |
1090 | |
1091 | LPUTF8 szFullName; |
1092 | LPCUTF8 szNamespace; |
1093 | LPCUTF8 szName; |
1094 | CMiniMdRW *pMiniMd = &(m_pStgdb->m_MiniMd); |
1095 | |
1096 | _ASSERTE(wzTypeName && ptk); |
1097 | |
1098 | |
1099 | |
1100 | LOG((LOGMD, "RegMeta::FindTypeRef(0x%8x, %ls, 0x%08x)\n" , |
1101 | tkResolutionScope, MDSTR(wzTypeName), ptk)); |
1102 | START_MD_PERF(); |
1103 | LOCKREAD(); |
1104 | |
1105 | // Convert the name to UTF8. |
1106 | PREFIX_ASSUME(wzTypeName != NULL); // caller might pass NULL, but they'll AV. |
1107 | UTF8STR(wzTypeName, szFullName); |
1108 | ns::SplitInline(szFullName, szNamespace, szName); |
1109 | |
1110 | // Look up the name. |
1111 | hr = ImportHelper::FindTypeRefByName(pMiniMd, tkResolutionScope, |
1112 | szNamespace, |
1113 | szName, |
1114 | ptk); |
1115 | ErrExit: |
1116 | |
1117 | STOP_MD_PERF(FindTypeRef); |
1118 | END_ENTRYPOINT_NOTHROW; |
1119 | |
1120 | return hr; |
1121 | } // STDMETHODIMP RegMeta::FindTypeRef() |
1122 | |
1123 | //******************************************************************************* |
1124 | // Find a given param of a Method. |
1125 | //******************************************************************************* |
1126 | HRESULT RegMeta::_FindParamOfMethod( // S_OK or error. |
1127 | mdMethodDef md, // [IN] The owning method of the param. |
1128 | ULONG iSeq, // [IN] The sequence # of the param. |
1129 | mdParamDef *pParamDef) // [OUT] Put ParamDef token here. |
1130 | { |
1131 | HRESULT hr; |
1132 | ParamRec *pParamRec; |
1133 | RID ridStart, ridEnd; |
1134 | RID pmRid; |
1135 | |
1136 | _ASSERTE(TypeFromToken(md) == mdtMethodDef && pParamDef); |
1137 | |
1138 | // get the methoddef record |
1139 | MethodRec *pMethodRec; |
1140 | IfFailRet(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec)); |
1141 | |
1142 | // figure out the start rid and end rid of the parameter list of this methoddef |
1143 | ridStart = m_pStgdb->m_MiniMd.getParamListOfMethod(pMethodRec); |
1144 | IfFailRet(m_pStgdb->m_MiniMd.getEndParamListOfMethod(RidFromToken(md), &ridEnd)); |
1145 | |
1146 | // loop through each param |
1147 | // <TODO>@consider: parameters are sorted by sequence. Maybe a binary search? |
1148 | //</TODO> |
1149 | for (; ridStart < ridEnd; ridStart++) |
1150 | { |
1151 | IfFailRet(m_pStgdb->m_MiniMd.GetParamRid(ridStart, &pmRid)); |
1152 | IfFailRet(m_pStgdb->m_MiniMd.GetParamRecord(pmRid, &pParamRec)); |
1153 | if (iSeq == m_pStgdb->m_MiniMd.getSequenceOfParam(pParamRec)) |
1154 | { |
1155 | // parameter has the sequence number matches what we are looking for |
1156 | *pParamDef = TokenFromRid(pmRid, mdtParamDef); |
1157 | return S_OK; |
1158 | } |
1159 | } |
1160 | return CLDB_E_RECORD_NOTFOUND; |
1161 | } // HRESULT RegMeta::_FindParamOfMethod() |
1162 | |
1163 | //******************************************************************************* |
1164 | // Given the signature, return the token for signature. |
1165 | //******************************************************************************* |
1166 | HRESULT RegMeta::_GetTokenFromSig( // S_OK or error. |
1167 | PCCOR_SIGNATURE pvSig, // [IN] Signature to define. |
1168 | ULONG cbSig, // [IN] Size of signature data. |
1169 | mdSignature *pmsig) // [OUT] returned signature token. |
1170 | { |
1171 | HRESULT hr = S_OK; |
1172 | |
1173 | _ASSERTE(pmsig); |
1174 | |
1175 | if (CheckDups(MDDupSignature)) |
1176 | { |
1177 | hr = ImportHelper::FindStandAloneSig(&(m_pStgdb->m_MiniMd), pvSig, cbSig, pmsig); |
1178 | if (SUCCEEDED(hr)) |
1179 | { |
1180 | if (IsENCOn()) |
1181 | return S_OK; |
1182 | else |
1183 | return META_S_DUPLICATE; |
1184 | } |
1185 | else if (hr != CLDB_E_RECORD_NOTFOUND) |
1186 | IfFailGo(hr); |
1187 | } |
1188 | |
1189 | // Create a new record. |
1190 | StandAloneSigRec *pSigRec; |
1191 | RID iSigRec; |
1192 | |
1193 | IfFailGo(m_pStgdb->m_MiniMd.AddStandAloneSigRecord(&pSigRec, &iSigRec)); |
1194 | |
1195 | // Set output parameter. |
1196 | *pmsig = TokenFromRid(iSigRec, mdtSignature); |
1197 | |
1198 | // Save signature. |
1199 | IfFailGo(m_pStgdb->m_MiniMd.PutBlob(TBL_StandAloneSig, StandAloneSigRec::COL_Signature, |
1200 | pSigRec, pvSig, cbSig)); |
1201 | IfFailGo(UpdateENCLog(*pmsig)); |
1202 | ErrExit: |
1203 | return hr; |
1204 | } // RegMeta::_GetTokenFromSig |
1205 | |