Merge pull request #11468 from sdmaclea/PR-ARM64-3092
[platform/upstream/coreclr.git] / src / vm / runtimehandles.cpp
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
6 #include "common.h"
7 #include "corhdr.h"
8 #include "runtimehandles.h"
9 #include "object.h"
10 #include "class.h"
11 #include "method.hpp"
12 #include "typehandle.h"
13 #include "field.h"
14 #include "siginfo.hpp"
15 #include "clsload.hpp"
16 #include "typestring.h"
17 #include "typeparse.h"
18 #include "holder.h"
19 #include "codeman.h"
20 #include "corhlpr.h"
21 #include "jitinterface.h"
22 #include "stackprobe.h"
23 #include "eeconfig.h"
24 #include "eehash.h"
25 #include "objecthandle.h"
26 #include "interoputil.h"
27 #include "typedesc.h"
28 #include "virtualcallstub.h"
29 #include "contractimpl.h"
30 #include "dynamicmethod.h"
31 #include "peimagelayout.inl"
32 #include "security.h"
33 #include "eventtrace.h"
34 #include "invokeutil.h"
35
36
37 FCIMPL3(FC_BOOL_RET, Utf8String::EqualsCaseSensitive, LPCUTF8 szLhs, LPCUTF8 szRhs, INT32 stringNumBytes)
38 {
39     CONTRACTL {
40         FCALL_CHECK;
41         PRECONDITION(CheckPointer(szLhs));
42         PRECONDITION(CheckPointer(szRhs));
43     }
44     CONTRACTL_END;
45
46     // Important: the string in pSsz isn't null terminated so the length must be used
47     // when performing operations on the string.
48
49     // At this point, both the left and right strings are guaranteed to have the
50     // same length.
51     FC_RETURN_BOOL(strncmp(szLhs, szRhs, stringNumBytes) == 0);
52 }
53 FCIMPLEND
54
55 BOOL QCALLTYPE Utf8String::EqualsCaseInsensitive(LPCUTF8 szLhs, LPCUTF8 szRhs, INT32 stringNumBytes)
56 {
57     QCALL_CONTRACT;
58
59     // Important: the string in pSsz isn't null terminated so the length must be used
60     // when performing operations on the string.
61     
62     BOOL fStringsEqual = FALSE;
63     
64     BEGIN_QCALL;
65
66     _ASSERTE(CheckPointer(szLhs));
67     _ASSERTE(CheckPointer(szRhs));
68
69     // At this point, both the left and right strings are guaranteed to have the
70     // same length. 
71     StackSString lhs(SString::Utf8, szLhs, stringNumBytes);
72     StackSString rhs(SString::Utf8, szRhs, stringNumBytes);
73
74     // We can use SString for simple case insensitive compares
75     fStringsEqual = lhs.EqualsCaseInsensitive(rhs);
76
77     END_QCALL;
78
79     return fStringsEqual;
80 }
81
82 ULONG QCALLTYPE Utf8String::HashCaseInsensitive(LPCUTF8 sz, INT32 stringNumBytes)
83 {
84     QCALL_CONTRACT;
85
86     // Important: the string in pSsz isn't null terminated so the length must be used
87     // when performing operations on the string.
88
89     ULONG hashValue = 0;
90     
91     BEGIN_QCALL;
92
93     StackSString str(SString::Utf8, sz, stringNumBytes);
94     hashValue = str.HashCaseInsensitive();
95
96     END_QCALL;
97
98     return hashValue;
99 }
100
101 static BOOL CheckCAVisibilityFromDecoratedType(MethodTable* pCAMT, MethodDesc* pCACtor, MethodTable* pDecoratedMT, Module* pDecoratedModule)
102 {
103     CONTRACTL
104     {
105         THROWS;
106         GC_TRIGGERS;
107         MODE_ANY;
108         PRECONDITION(CheckPointer(pCAMT));
109         PRECONDITION(CheckPointer(pCACtor, NULL_OK));
110         PRECONDITION(CheckPointer(pDecoratedMT, NULL_OK));
111         PRECONDITION(CheckPointer(pDecoratedModule));
112     }
113     CONTRACTL_END;
114
115     DWORD dwAttr = mdPublic;
116
117     if (pCACtor != NULL)
118     {
119         // Allowing a dangerous method to be called in custom attribute instantiation is, well, dangerous.
120         // E.g. a malicious user can craft a custom attribute record that fools us into creating a DynamicMethod
121         // object attached to typeof(System.Reflection.CustomAttribute) and thus gain access to mscorlib internals.
122         if (InvokeUtil::IsDangerousMethod(pCACtor))
123             return FALSE;
124
125         _ASSERTE(pCACtor->IsCtor());
126
127         dwAttr = pCACtor->GetAttrs();
128     }
129     
130     StaticAccessCheckContext accessContext(NULL, pDecoratedMT, pDecoratedModule->GetAssembly());
131
132     // Don't do transparency check here. Custom attributes have different transparency rules. 
133     // The checks are done by AllowCriticalCustomAttributes and CheckLinktimeDemands in CustomAttribute.cs.
134     return ClassLoader::CanAccess(
135         &accessContext, 
136         pCAMT,
137         pCAMT->GetAssembly(), 
138         dwAttr,
139         pCACtor,
140         NULL,
141         *AccessCheckOptions::s_pNormalAccessChecks,
142         FALSE,
143         FALSE);
144 }
145
146 BOOL QCALLTYPE RuntimeMethodHandle::IsCAVisibleFromDecoratedType(
147     EnregisteredTypeHandle  targetTypeHandle,
148     MethodDesc *            pTargetCtor,
149     EnregisteredTypeHandle  sourceTypeHandle,
150     QCall::ModuleHandle     sourceModuleHandle)
151 {
152     QCALL_CONTRACT;
153
154     BOOL bResult = TRUE;
155
156     BEGIN_QCALL;
157     TypeHandle sourceHandle = TypeHandle::FromPtr(sourceTypeHandle);
158     TypeHandle targetHandle = TypeHandle::FromPtr(targetTypeHandle);
159
160     _ASSERTE((sourceHandle.IsNull() || !sourceHandle.IsTypeDesc()) &&
161              !targetHandle.IsNull() &&
162              !targetHandle.IsTypeDesc());
163
164     if (sourceHandle.IsTypeDesc() ||
165         targetHandle.IsNull() || 
166         targetHandle.IsTypeDesc())
167         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
168
169     bResult = CheckCAVisibilityFromDecoratedType(targetHandle.AsMethodTable(), pTargetCtor, sourceHandle.AsMethodTable(), sourceModuleHandle);
170     END_QCALL;
171
172     return bResult;
173 }
174
175 // static
176 BOOL QCALLTYPE RuntimeMethodHandle::IsSecurityCritical(MethodDesc *pMD)
177 {
178     CONTRACTL
179     {
180         QCALL_CHECK;
181         PRECONDITION(CheckPointer(pMD));
182     }
183     CONTRACTL_END;
184
185     BOOL fIsCritical = TRUE;
186
187     BEGIN_QCALL;
188
189     if (pMD == NULL)
190         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
191
192     fIsCritical = Security::IsMethodCritical(pMD);
193
194     END_QCALL;
195
196     return fIsCritical;
197 }
198
199 // static
200 BOOL QCALLTYPE RuntimeMethodHandle::IsSecuritySafeCritical(MethodDesc *pMD)
201 {
202     CONTRACTL
203     {
204         QCALL_CHECK;
205         PRECONDITION(CheckPointer(pMD));
206     }
207     CONTRACTL_END;
208
209     BOOL fIsSafeCritical = TRUE;
210
211     BEGIN_QCALL;
212
213     if (pMD == NULL)
214         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
215
216     fIsSafeCritical = Security::IsMethodSafeCritical(pMD);
217
218     END_QCALL;
219
220     return fIsSafeCritical;
221 }
222
223 // static
224 BOOL QCALLTYPE RuntimeMethodHandle::IsSecurityTransparent(MethodDesc *pMD)
225 {
226     CONTRACTL
227     {
228         QCALL_CHECK;
229         PRECONDITION(CheckPointer(pMD));
230     }
231     CONTRACTL_END;
232
233     BOOL fIsTransparent = TRUE;
234
235     BEGIN_QCALL;
236
237     if (pMD == NULL)
238         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
239
240     fIsTransparent = Security::IsMethodTransparent(pMD);
241
242     END_QCALL;
243
244     return fIsTransparent;
245 }
246
247 FCIMPL2(FC_BOOL_RET, RuntimeMethodHandle::IsTokenSecurityTransparent, ReflectModuleBaseObject *pModuleUNSAFE, INT32 tkToken) {
248     CONTRACTL {
249         FCALL_CHECK;
250     }
251     CONTRACTL_END;
252
253     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
254
255     if(refModule == NULL)
256         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
257
258     Module *pModule = refModule->GetModule();
259
260     BOOL bIsSecurityTransparent = TRUE;
261     
262     HELPER_METHOD_FRAME_BEGIN_RET_1(refModule);
263     {
264         bIsSecurityTransparent = Security::IsTokenTransparent(pModule, tkToken);
265     }
266     HELPER_METHOD_FRAME_END();
267
268     FC_RETURN_BOOL(bIsSecurityTransparent );
269
270 }
271 FCIMPLEND
272
273 static bool DoAttributeTransparencyChecks(Assembly *pAttributeAssembly, Assembly *pDecoratedAssembly)
274 {
275     CONTRACTL
276     {
277         THROWS;
278         MODE_COOPERATIVE;
279         GC_TRIGGERS;
280         PRECONDITION(CheckPointer(pAttributeAssembly));
281         PRECONDITION(CheckPointer(pDecoratedAssembly));
282     }
283     CONTRACTL_END;
284
285     // Do transparency checks - if both the decorated assembly and attribute use the v4 security model,
286     // then we can do a direct transparency check.  However, if the decorated assembly uses the v2
287     // security model, then we need to convert the security critical attribute to looking as though it
288     // has a LinkDemand for full trust.
289     const SecurityTransparencyBehavior *pTargetTransparency = pDecoratedAssembly->GetSecurityTransparencyBehavior();
290     const SecurityTransparencyBehavior *pAttributeTransparency = pAttributeAssembly->GetSecurityTransparencyBehavior();
291
292     // v2 transparency did not impose checks for using its custom attributes, so if the attribute is
293     // defined in an assembly using the v2 transparency model then we don't need to do any
294     // additional checks.
295     if (pAttributeTransparency->DoAttributesRequireTransparencyChecks())
296     {
297         if (pTargetTransparency->CanTransparentCodeCallLinkDemandMethods() &&
298             pAttributeTransparency->CanCriticalMembersBeConvertedToLinkDemand())
299         {
300             // We have a v4 critical attribute being applied to a v2 transparent target. Since v2
301             // transparency doesn't understand externally visible critical attributes, we convert the
302             // attribute to a LinkDemand for full trust.  v2 transparency did not convert
303             // LinkDemands on its attributes into full demands so we do not do that second level of
304             // conversion here either.
305             Security::FullTrustLinkDemand(pDecoratedAssembly);
306             return true;
307         }
308         else
309         {
310             // If we are here either the target of the attribute uses the v4 security model, or the
311             // attribute itself uses the v2 model.  In these cases, we cannot perform a conversion of
312             // the critical attribute into a LinkDemand, and we have an error condition.
313             return false;
314         }
315     }
316
317     return true;
318 }
319
320 FCIMPL3(void, RuntimeMethodHandle::CheckLinktimeDemands, ReflectMethodObject *pMethodUNSAFE, ReflectModuleBaseObject *pModuleUNSAFE, CLR_BOOL isDecoratedTargetSecurityTransparent) 
321 {
322     CONTRACTL 
323     {
324         FCALL_CHECK;
325         PRECONDITION(CheckPointer(pModuleUNSAFE));
326         PRECONDITION(CheckPointer(pMethodUNSAFE));
327     }
328     CONTRACTL_END;
329
330     if(!Security::IsTransparencyEnforcementEnabled())
331     {
332         FCUnique(0xb0);
333         return;
334     }
335
336     REFLECTMETHODREF refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
337     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
338
339     HELPER_METHOD_FRAME_BEGIN_2(refMethod, refModule);
340     {
341         MethodDesc *pCallee = refMethod->GetMethod(); // pCallee is the CA ctor or CA setter method
342         Module *pDecoratedModule = refModule->GetModule();
343
344         bool isAttributeSecurityCritical = Security::IsMethodCritical(pCallee) &&
345                                            !Security::IsMethodSafeCritical(pCallee);
346
347         if (isDecoratedTargetSecurityTransparent && isAttributeSecurityCritical)
348         {
349             if (!DoAttributeTransparencyChecks(pCallee->GetAssembly(), pDecoratedModule->GetAssembly()))
350             {
351                 SecurityTransparent::ThrowMethodAccessException(pCallee);
352             }
353         }
354
355     }
356     HELPER_METHOD_FRAME_END();
357 }
358 FCIMPLEND
359
360 NOINLINE static ReflectClassBaseObject* GetRuntimeTypeHelper(LPVOID __me, TypeHandle typeHandle, OBJECTREF keepAlive)
361 {
362     FC_INNER_PROLOG_NO_ME_SETUP();
363     if (typeHandle.AsPtr() == NULL)
364         return NULL;
365     
366     // RuntimeTypeHandle::GetRuntimeType has picked off the most common case, but does not cover array types.
367     // Before we do the really heavy weight option of setting up a helper method frame, check if we have to. 
368     OBJECTREF refType = typeHandle.GetManagedClassObjectFast();
369     if (refType != NULL)
370         return (ReflectClassBaseObject*)OBJECTREFToObject(refType);
371
372     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
373     refType = typeHandle.GetManagedClassObject();
374     HELPER_METHOD_FRAME_END();
375
376     FC_INNER_EPILOG();
377     return (ReflectClassBaseObject*)OBJECTREFToObject(refType);
378 }
379
380 #define RETURN_CLASS_OBJECT(typeHandle, keepAlive) FC_INNER_RETURN(ReflectClassBaseObject*, GetRuntimeTypeHelper(__me, typeHandle, keepAlive))
381
382 NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive)
383 {
384     FC_INNER_PROLOG_NO_ME_SETUP();
385     if (pModule == NULL)
386         return NULL;
387     
388     DomainFile * pDomainFile = pModule->FindDomainFile(GetAppDomain());
389
390     OBJECTREF refModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
391
392     if(refModule != NULL)
393         return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
394
395     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
396     refModule = pModule->GetExposedObject();
397     HELPER_METHOD_FRAME_END();
398
399     FC_INNER_EPILOG();
400     return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
401 }
402
403 NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive)
404 {
405     FC_INNER_PROLOG_NO_ME_SETUP();
406     if (pAssembly == NULL)
407         return NULL;
408     
409     OBJECTREF refAssembly = (pAssembly != NULL) ? pAssembly->GetExposedAssemblyObjectIfExists() : NULL;
410
411     if(refAssembly != NULL)
412         return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
413
414     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
415     refAssembly = pAssembly->GetExposedAssemblyObject();
416     HELPER_METHOD_FRAME_END();
417
418     FC_INNER_EPILOG();
419     return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
420 }
421
422
423 // This is the routine that is called by the 'typeof()' operator in C#.  It is one of the most commonly used
424 // reflection operations. This call should be optimized away in nearly all situations
425 FCIMPL1_V(ReflectClassBaseObject*, RuntimeTypeHandle::GetTypeFromHandle, FCALLRuntimeTypeHandle th)
426 {
427     FCALL_CONTRACT;
428     
429     FCUnique(0x31);
430     return FCALL_RTH_TO_REFLECTCLASS(th);
431 }
432 FCIMPLEND
433
434 FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetRuntimeType, EnregisteredTypeHandle th)
435 {
436     FCALL_CONTRACT;
437     
438     TypeHandle typeHandle = TypeHandle::FromPtr(th);
439     _ASSERTE(CheckPointer(typeHandle.AsPtr(), NULL_OK));
440     if (typeHandle.AsPtr()!= NULL)
441     {
442         if (!typeHandle.IsTypeDesc())
443         {
444             OBJECTREF typePtr = typeHandle.AsMethodTable()->GetManagedClassObjectIfExists();
445             if (typePtr != NULL)
446             {
447                 return (ReflectClassBaseObject*)OBJECTREFToObject(typePtr);
448             }
449         }
450     }
451     else 
452         return NULL;
453
454     RETURN_CLASS_OBJECT(typeHandle, NULL);
455 }
456 FCIMPLEND
457
458 FCIMPL1_V(EnregisteredTypeHandle, RuntimeTypeHandle::GetValueInternal, FCALLRuntimeTypeHandle RTH)
459 {
460     FCALL_CONTRACT;
461
462     if (FCALL_RTH_TO_REFLECTCLASS(RTH) == NULL)
463         return 0;
464
465     return FCALL_RTH_TO_REFLECTCLASS(RTH) ->GetType().AsPtr();
466 }
467 FCIMPLEND
468
469 // TypeEqualsHelper and TypeNotEqualsHelper are almost identical.
470 // Unfortunately we cannot combime them because they need to hardcode the caller's name
471 NOINLINE static BOOL TypeEqualSlow(OBJECTREF refL, OBJECTREF refR, LPVOID __me)
472 {
473     BOOL ret = FALSE;
474
475     FC_INNER_PROLOG_NO_ME_SETUP();
476
477     _ASSERTE(refL != NULL && refR != NULL);
478
479     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, refL, refR);
480
481     MethodDescCallSite TypeEqualsMethod(METHOD__OBJECT__EQUALS, &refL);
482
483     ARG_SLOT args[] = 
484     {
485         ObjToArgSlot(refL),
486         ObjToArgSlot(refR)
487     };
488
489     ret = TypeEqualsMethod.Call_RetBool(args);
490
491     HELPER_METHOD_FRAME_END();
492
493     FC_INNER_EPILOG();
494
495     return ret;
496 }
497
498
499
500 #include <optsmallperfcritical.h>
501
502 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::TypeEQ, Object* left, Object* right)
503 {
504     FCALL_CONTRACT;
505
506     OBJECTREF refL = (OBJECTREF)left;
507     OBJECTREF refR = (OBJECTREF)right;
508
509     if (refL == refR)
510     {
511         FC_RETURN_BOOL(TRUE);
512     }
513
514     if (!refL || !refR)
515     {
516         FC_RETURN_BOOL(FALSE);
517     }
518
519     if ((refL->GetMethodTable() == g_pRuntimeTypeClass || refR->GetMethodTable() == g_pRuntimeTypeClass))
520     {
521         // Quick path for negative common case
522         FC_RETURN_BOOL(FALSE);
523     }
524
525     // The fast path didn't get us the result
526     // Let's try the slow path: refL.Equals(refR);
527     FC_INNER_RETURN(FC_BOOL_RET, (FC_BOOL_RET)(!!TypeEqualSlow(refL, refR, __me)));
528 }
529 FCIMPLEND
530
531 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::TypeNEQ, Object* left, Object* right)
532 {
533     FCALL_CONTRACT;
534
535     OBJECTREF refL = (OBJECTREF)left;
536     OBJECTREF refR = (OBJECTREF)right;
537
538     if (refL == refR)
539     {
540         FC_RETURN_BOOL(FALSE);
541     }
542
543     if (!refL || !refR)
544     {
545         FC_RETURN_BOOL(TRUE);
546     }
547
548     if ((refL->GetMethodTable() == g_pRuntimeTypeClass || refR->GetMethodTable() == g_pRuntimeTypeClass))
549     {
550         // Quick path for negative common case
551         FC_RETURN_BOOL(TRUE);
552     }
553
554     // The fast path didn't get us the result
555     // Let's try the slow path: refL.Equals(refR);
556     FC_INNER_RETURN(FC_BOOL_RET, (FC_BOOL_RET)(!TypeEqualSlow(refL, refR, __me)));
557 }
558 FCIMPLEND
559
560 #include <optdefault.h>
561
562
563
564
565 #ifdef FEATURE_COMINTEROP
566 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsWindowsRuntimeObjectType, ReflectClassBaseObject *rtTypeUNSAFE)
567 {
568     FCALL_CONTRACT;
569
570     BOOL isWindowsRuntimeType = FALSE;
571
572     TypeHandle typeHandle = rtTypeUNSAFE->GetType();
573     MethodTable *pMT = typeHandle.GetMethodTable();
574
575     if (pMT != NULL)
576     {
577         isWindowsRuntimeType = pMT->IsWinRTObjectType();
578     }
579
580     FC_RETURN_BOOL(isWindowsRuntimeType);
581 }
582 FCIMPLEND
583
584 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsTypeExportedToWindowsRuntime, ReflectClassBaseObject *rtTypeUNSAFE)
585 {
586     FCALL_CONTRACT;
587
588     BOOL isExportedToWinRT = FALSE;
589
590     TypeHandle typeHandle = rtTypeUNSAFE->GetType();
591     MethodTable *pMT = typeHandle.GetMethodTable();
592
593     if (pMT != NULL)
594     {
595         isExportedToWinRT = pMT->IsExportedToWinRT();
596     }
597
598     FC_RETURN_BOOL(isExportedToWinRT);
599 }
600 FCIMPLEND
601 #endif // FEATURE_COMINTEROP
602
603 NOINLINE static MethodDesc * RestoreMethodHelper(MethodDesc * pMethod, LPVOID __me)
604 {
605     FC_INNER_PROLOG_NO_ME_SETUP();
606
607     HELPER_METHOD_FRAME_BEGIN_RET_0();
608     pMethod->CheckRestore();
609     HELPER_METHOD_FRAME_END();
610
611     FC_INNER_EPILOG();
612
613     return pMethod;
614 }
615
616 FCIMPL1(MethodDesc *, RuntimeTypeHandle::GetFirstIntroducedMethod, ReflectClassBaseObject *pTypeUNSAFE) {
617     CONTRACTL {
618         FCALL_CHECK;
619         PRECONDITION(CheckPointer(pTypeUNSAFE));
620     }
621     CONTRACTL_END;
622
623     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
624     TypeHandle typeHandle = refType->GetType();
625     
626     if (typeHandle.IsGenericVariable())
627         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
628         
629     if (typeHandle.IsTypeDesc()) {
630         if (!typeHandle.IsArray()) 
631             return NULL;
632     }
633
634     MethodTable* pMT = typeHandle.GetMethodTable();
635     if (pMT == NULL)
636         return NULL;
637
638     MethodDesc* pMethod = MethodTable::IntroducedMethodIterator::GetFirst(pMT);
639
640     // The only method that can show up here unrestored is instantiated methods. Check for it before performing the expensive IsRestored() check.
641     if (pMethod != NULL && pMethod->GetClassification() == mcInstantiated && !pMethod->IsRestored()) {
642         FC_INNER_RETURN(MethodDesc *, RestoreMethodHelper(pMethod, __me));
643     }
644
645     _ASSERTE(pMethod == NULL || pMethod->IsRestored());
646     return pMethod;
647 }
648 FCIMPLEND
649
650 #include <optsmallperfcritical.h>
651 FCIMPL1(void, RuntimeTypeHandle::GetNextIntroducedMethod, MethodDesc ** ppMethod) {
652     CONTRACTL {
653         FCALL_CHECK;
654         PRECONDITION(CheckPointer(ppMethod));
655         PRECONDITION(CheckPointer(*ppMethod));
656     }
657     CONTRACTL_END;
658
659     MethodDesc *pMethod = MethodTable::IntroducedMethodIterator::GetNext(*ppMethod);
660
661     *ppMethod = pMethod;
662
663     if (pMethod != NULL && pMethod->GetClassification() == mcInstantiated && !pMethod->IsRestored()) {
664         FC_INNER_RETURN_VOID(RestoreMethodHelper(pMethod, __me));
665     }
666
667     _ASSERTE(pMethod == NULL || pMethod->IsRestored());
668 }
669 FCIMPLEND
670 #include <optdefault.h>
671
672 FCIMPL1(INT32, RuntimeTypeHandle::GetCorElementType, ReflectClassBaseObject *pTypeUNSAFE) {
673     CONTRACTL {
674         FCALL_CHECK;
675     }
676     CONTRACTL_END;
677
678     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
679
680     if (refType == NULL)
681         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
682
683     return refType->GetType().GetSignatureCorElementType();
684 }
685 FCIMPLEND
686
687 FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssembly, ReflectClassBaseObject *pTypeUNSAFE) {
688     CONTRACTL {
689         FCALL_CHECK;
690     }
691     CONTRACTL_END;
692
693     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
694
695     if (refType == NULL)
696         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
697
698     DomainFile *pDomainFile = NULL;
699     
700         Module *pModule = refType->GetType().GetAssembly()->GetManifestModule();
701
702             pDomainFile = pModule->FindDomainFile(GetAppDomain());
703 #ifdef FEATURE_LOADER_OPTIMIZATION        
704         if (pDomainFile == NULL)
705         {
706             HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
707             
708             pDomainFile = GetAppDomain()->LoadDomainNeutralModuleDependency(pModule, FILE_LOADED);
709
710             HELPER_METHOD_FRAME_END();
711         }
712 #endif // FEATURE_LOADER_OPTIMIZATION        
713
714
715     FC_RETURN_ASSEMBLY_OBJECT((DomainAssembly *)pDomainFile, refType);
716 }
717 FCIMPLEND
718
719
720 FCIMPL1(FC_BOOL_RET, RuntimeFieldHandle::AcquiresContextFromThis, FieldDesc *pField)
721 {
722     CONTRACTL {
723         FCALL_CHECK;
724         PRECONDITION(CheckPointer(pField));
725     }
726     CONTRACTL_END;
727
728     FC_RETURN_BOOL(pField->IsSharedByGenericInstantiations());
729
730 }
731 FCIMPLEND
732
733 // static
734 BOOL QCALLTYPE RuntimeFieldHandle::IsSecurityCritical(FieldDesc *pFD)
735 {
736     CONTRACTL
737     {
738         QCALL_CHECK;
739         PRECONDITION(CheckPointer(pFD));
740     }
741     CONTRACTL_END;
742
743     BOOL fIsCritical = FALSE;
744
745     BEGIN_QCALL;
746
747     fIsCritical = Security::IsFieldCritical(pFD);
748
749     END_QCALL;
750
751     return fIsCritical;
752 }
753
754 // static
755 BOOL QCALLTYPE RuntimeFieldHandle::IsSecuritySafeCritical(FieldDesc *pFD)
756 {
757     CONTRACTL
758     {
759         QCALL_CHECK;
760         PRECONDITION(CheckPointer(pFD));
761     }
762     CONTRACTL_END;
763
764     BOOL fIsSafeCritical = FALSE;
765
766     BEGIN_QCALL;
767
768     fIsSafeCritical = Security::IsFieldSafeCritical(pFD);
769
770     END_QCALL;
771
772     return fIsSafeCritical;
773 }
774
775 // static
776 BOOL QCALLTYPE RuntimeFieldHandle::IsSecurityTransparent(FieldDesc *pFD)
777 {
778     CONTRACTL
779     {
780         QCALL_CHECK;
781         PRECONDITION(CheckPointer(pFD));
782     }
783     CONTRACTL_END;
784
785     BOOL fIsTransparent = FALSE;
786
787     BEGIN_QCALL;
788
789     fIsTransparent = Security::IsFieldTransparent(pFD);
790
791     END_QCALL;
792
793     return fIsTransparent;
794 }
795
796 // static
797 void QCALLTYPE RuntimeFieldHandle::CheckAttributeAccess(FieldDesc *pFD, QCall::ModuleHandle pModule)
798 {
799     CONTRACTL
800     {
801         QCALL_CHECK;
802         PRECONDITION(CheckPointer(pFD));
803         PRECONDITION(CheckPointer(pModule.m_pModule));
804     }
805     CONTRACTL_END;
806     
807     if(!Security::IsTransparencyEnforcementEnabled())
808     {
809         FCUnique(0xb1);
810         return;
811     }
812
813     BEGIN_QCALL;
814
815     if (Security::IsFieldCritical(pFD) && !Security::IsFieldSafeCritical(pFD))
816     {
817         GCX_COOP();
818
819         if (!DoAttributeTransparencyChecks(pFD->GetModule()->GetAssembly(), pModule->GetAssembly()))
820         {
821             ThrowFieldAccessException(NULL, pFD, TRUE, IDS_E_CRITICAL_FIELD_ACCESS_DENIED);
822         }
823     }
824
825     END_QCALL;
826 }
827
828 FCIMPL1(ReflectModuleBaseObject*, RuntimeTypeHandle::GetModule, ReflectClassBaseObject *pTypeUNSAFE) {
829     CONTRACTL {
830         FCALL_CHECK;
831     }
832     CONTRACTL_END;
833     
834     Module *result;
835
836     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
837
838     if (refType == NULL)
839         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
840
841     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
842
843     result = refType->GetType().GetModule();
844
845     END_SO_INTOLERANT_CODE;
846
847     FC_RETURN_MODULE_OBJECT(result, refType);
848 }
849 FCIMPLEND
850
851 FCIMPL1(ReflectClassBaseObject *, RuntimeTypeHandle::GetBaseType, ReflectClassBaseObject *pTypeUNSAFE) {
852     CONTRACTL {
853         FCALL_CHECK;
854     }
855     CONTRACTL_END;
856
857     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
858
859     if (refType == NULL)
860         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
861
862     TypeHandle typeHandle = refType->GetType();
863     
864     if (typeHandle.IsGenericVariable())
865         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
866         
867     if (typeHandle.IsTypeDesc()) {
868         if (!typeHandle.IsArray()) 
869             return NULL;
870     }
871     
872     RETURN_CLASS_OBJECT(typeHandle.GetParent(), refType);
873 }
874 FCIMPLEND
875      
876 FCIMPL1(ReflectClassBaseObject *, RuntimeTypeHandle::GetElementType, ReflectClassBaseObject *pTypeUNSAFE) {
877     CONTRACTL {
878         FCALL_CHECK;
879     }
880     CONTRACTL_END;
881     
882     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
883
884     if (refType == NULL)
885         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
886
887     TypeHandle typeHandle = refType->GetType();
888
889     if (!typeHandle.IsTypeDesc())
890         return 0;   
891
892     if (typeHandle.IsGenericVariable())
893         return 0;
894
895     TypeHandle typeReturn;
896
897     if (typeHandle.IsArray()) 
898         typeReturn = typeHandle.AsArray()->GetArrayElementTypeHandle();
899     else
900         typeReturn = typeHandle.AsTypeDesc()->GetTypeParam();
901
902     RETURN_CLASS_OBJECT(typeReturn, refType);
903 }
904 FCIMPLEND
905             
906 FCIMPL1(INT32, RuntimeTypeHandle::GetArrayRank, ReflectClassBaseObject *pTypeUNSAFE) {
907     CONTRACTL {
908         FCALL_CHECK;
909         PRECONDITION(CheckPointer(pTypeUNSAFE));
910         PRECONDITION(pTypeUNSAFE->GetType().IsArray());
911     }
912     CONTRACTL_END;
913
914     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
915
916     return (INT32)refType->GetType().AsArray()->GetRank();   
917 }
918 FCIMPLEND
919
920 FCIMPL1(INT32, RuntimeTypeHandle::GetNumVirtuals, ReflectClassBaseObject *pTypeUNSAFE) {
921     CONTRACTL {
922         FCALL_CHECK;
923     }
924     CONTRACTL_END;
925     
926     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
927
928     if (refType == NULL)
929         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
930
931     TypeHandle typeHandle = refType->GetType();
932
933     if (typeHandle.IsGenericVariable())
934         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
935     
936     MethodTable *pMT = typeHandle.GetMethodTable();
937
938     if (pMT) 
939         return (INT32)pMT->GetNumVirtuals();
940     else
941         return 0; //REVIEW: should this return the number of methods in Object?
942 }
943 FCIMPLEND
944
945 FCIMPL2(MethodDesc *, RuntimeTypeHandle::GetMethodAt, ReflectClassBaseObject *pTypeUNSAFE, INT32 slot) {
946     CONTRACTL {
947         FCALL_CHECK;
948     }
949     CONTRACTL_END;
950     
951     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
952
953     if (refType == NULL)
954         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
955
956     TypeHandle typeHandle = refType->GetType();
957
958     MethodDesc* pRetMethod = NULL;
959
960     if (typeHandle.IsGenericVariable())
961         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
962
963     if (slot < 0 || slot >= (INT32)typeHandle.GetMethodTable()->GetNumVirtuals())
964         FCThrowRes(kArgumentException, W("Arg_ArgumentOutOfRangeException"));      
965
966     HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
967     pRetMethod = typeHandle.GetMethodTable()->GetMethodDescForSlot((DWORD)slot);
968     HELPER_METHOD_FRAME_END();
969
970     return pRetMethod;
971 }
972
973 FCIMPLEND
974
975 FCIMPL3(FC_BOOL_RET, RuntimeTypeHandle::GetFields, ReflectClassBaseObject *pTypeUNSAFE, INT32 **result, INT32 *pCount) {
976     CONTRACTL {
977         FCALL_CHECK;
978     }
979     CONTRACTL_END;
980     
981     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
982     if (refType == NULL)
983         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
984
985     TypeHandle typeHandle = refType->GetType();
986     
987     if (!pCount || !result)
988         FCThrow(kArgumentNullException);
989
990     if (typeHandle.IsGenericVariable())
991         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
992     
993     if (typeHandle.IsTypeDesc()) {
994         *pCount = 0;
995         FC_RETURN_BOOL(TRUE);
996     }
997
998     MethodTable *pMT= typeHandle.GetMethodTable();
999     if (!pMT)
1000         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1001
1002     BOOL retVal = FALSE;
1003     HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
1004     // <TODO>Check this approximation - we may be losing exact type information </TODO>
1005     ApproxFieldDescIterator fdIterator(pMT, ApproxFieldDescIterator::ALL_FIELDS);
1006     INT32 count = (INT32)fdIterator.Count();
1007
1008     if (count > *pCount) 
1009     {
1010         *pCount = count;
1011     } 
1012     else 
1013     {
1014         for(INT32 i = 0; i < count; i ++)
1015             result[i] = (INT32*)fdIterator.Next();
1016         
1017         *pCount = count;
1018         retVal = TRUE;
1019     }
1020     HELPER_METHOD_FRAME_END();
1021     FC_RETURN_BOOL(retVal);
1022 }
1023 FCIMPLEND
1024
1025 void QCALLTYPE RuntimeMethodHandle::ConstructInstantiation(MethodDesc * pMethod, DWORD format, QCall::StringHandleOnStack retString)
1026 {
1027     QCALL_CONTRACT;
1028
1029     BEGIN_QCALL;
1030
1031     StackSString ss;
1032     TypeString::AppendInst(ss, pMethod->LoadMethodInstantiation(), format);
1033     retString.Set(ss);
1034     
1035     END_QCALL;
1036 }
1037
1038 void QCALLTYPE RuntimeTypeHandle::ConstructName(EnregisteredTypeHandle pTypeHandle, DWORD format, QCall::StringHandleOnStack retString)
1039 {
1040     QCALL_CONTRACT;
1041       
1042     BEGIN_QCALL;
1043
1044     StackSString ss;    
1045     TypeString::AppendType(ss, TypeHandle::FromPtr(pTypeHandle), format);
1046     retString.Set(ss);
1047
1048     END_QCALL;
1049 }
1050
1051 PTRARRAYREF CopyRuntimeTypeHandles(TypeHandle * prgTH, FixupPointer<TypeHandle> * prgTH2, INT32 numTypeHandles, BinderClassID arrayElemType)
1052 {
1053     CONTRACTL {
1054         THROWS;
1055         GC_TRIGGERS;
1056         MODE_COOPERATIVE;
1057     }
1058     CONTRACTL_END;
1059
1060     PTRARRAYREF refReturn = NULL;
1061     PTRARRAYREF refArray  = NULL;
1062
1063     if (numTypeHandles == 0)
1064         return NULL;
1065
1066     _ASSERTE((prgTH != NULL) || (prgTH2 != NULL));
1067     if (prgTH != NULL)
1068     {
1069         _ASSERTE(prgTH2 == NULL);
1070     }
1071
1072     GCPROTECT_BEGIN(refArray);
1073     TypeHandle thRuntimeType = TypeHandle(MscorlibBinder::GetClass(arrayElemType));
1074     TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(thRuntimeType, ELEMENT_TYPE_SZARRAY);
1075     refArray = (PTRARRAYREF)AllocateArrayEx(arrayHandle, &numTypeHandles, 1);
1076
1077     for (INT32 i = 0; i < numTypeHandles; i++)
1078     {
1079         TypeHandle th;
1080
1081         if (prgTH != NULL)
1082             th = prgTH[i];
1083         else
1084             th = prgTH2[i].GetValue();
1085
1086         OBJECTREF refType = th.GetManagedClassObject();
1087         refArray->SetAt(i, refType);
1088     }
1089
1090     refReturn = refArray;
1091     GCPROTECT_END();
1092
1093     return refReturn;
1094 }
1095
1096 void QCALLTYPE RuntimeTypeHandle::GetConstraints(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retTypeArray)
1097 {
1098     QCALL_CONTRACT;
1099
1100     TypeHandle* constraints = NULL;
1101     
1102     BEGIN_QCALL;
1103     
1104     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1105     
1106     if (!typeHandle.IsGenericVariable())
1107         COMPlusThrow(kArgumentException, W("Arg_InvalidHandle"));
1108
1109         TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();              
1110     
1111     DWORD dwCount;
1112     constraints = pGenericVariable->GetConstraints(&dwCount);
1113
1114     GCX_COOP();
1115     retTypeArray.Set(CopyRuntimeTypeHandles(constraints, NULL, dwCount, CLASS__TYPE));
1116
1117     END_QCALL;
1118
1119     return;
1120 }
1121
1122 FCIMPL1(PtrArray*, RuntimeTypeHandle::GetInterfaces, ReflectClassBaseObject *pTypeUNSAFE) {
1123     CONTRACTL {
1124         FCALL_CHECK;
1125     }
1126     CONTRACTL_END;
1127     
1128     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1129
1130     if (refType == NULL)
1131         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1132
1133     TypeHandle typeHandle = refType->GetType();
1134     
1135   if (typeHandle.IsGenericVariable())
1136         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1137     
1138     INT32 ifaceCount = 0; 
1139   
1140     PTRARRAYREF refRetVal  = NULL;
1141     HELPER_METHOD_FRAME_BEGIN_RET_2(refRetVal, refType);
1142     {
1143         if (typeHandle.IsTypeDesc())
1144         {
1145             if (typeHandle.IsArray())
1146             {
1147                 ifaceCount = typeHandle.GetMethodTable()->GetNumInterfaces();            
1148             }
1149             else
1150             {
1151                 ifaceCount = 0;
1152             }
1153         }
1154         else
1155         {
1156             ifaceCount = typeHandle.GetMethodTable()->GetNumInterfaces();
1157         }
1158
1159         // Allocate the array
1160         if (ifaceCount > 0)
1161         {            
1162             TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pRuntimeTypeClass), ELEMENT_TYPE_SZARRAY);
1163             refRetVal = (PTRARRAYREF)AllocateArrayEx(arrayHandle, &ifaceCount, 1);
1164         
1165             // populate type array
1166             UINT i = 0;
1167             
1168             MethodTable::InterfaceMapIterator it = typeHandle.GetMethodTable()->IterateInterfaceMap();
1169             while (it.Next())
1170             {
1171                 OBJECTREF refInterface = it.GetInterface()->GetManagedClassObject();
1172                 refRetVal->SetAt(i, refInterface);
1173                 _ASSERTE(refRetVal->GetAt(i) != NULL);
1174                 i++;
1175             }
1176         }
1177     }
1178     HELPER_METHOD_FRAME_END();
1179
1180     return (PtrArray*)OBJECTREFToObject(refRetVal);
1181 }
1182 FCIMPLEND
1183
1184 FCIMPL1(INT32, RuntimeTypeHandle::GetAttributes, ReflectClassBaseObject *pTypeUNSAFE) {
1185     CONTRACTL {
1186         FCALL_CHECK;
1187     }
1188     CONTRACTL_END;
1189     
1190     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1191
1192     if (refType == NULL)
1193         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1194
1195     TypeHandle typeHandle = refType->GetType();
1196       
1197     if (typeHandle.IsTypeDesc()) {
1198
1199         if (typeHandle.IsGenericVariable()) {
1200             return tdPublic;        
1201         }
1202     
1203         if (!typeHandle.IsArray()) 
1204             return 0;
1205     }
1206
1207 #ifdef FEATURE_COMINTEROP
1208     // __ComObject types are always public.
1209     if (IsComObjectClass(typeHandle))
1210         return (typeHandle.GetMethodTable()->GetAttrClass() & tdVisibilityMask) | tdPublic;
1211 #endif // FEATURE_COMINTEROP
1212
1213     INT32 ret = 0;
1214     
1215     ret = (INT32)typeHandle.GetMethodTable()->GetAttrClass();
1216     return ret;
1217 }
1218 FCIMPLEND
1219
1220
1221 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsValueType, ReflectClassBaseObject *pTypeUNSAFE)
1222 {
1223     CONTRACTL {
1224         FCALL_CHECK;
1225     }
1226     CONTRACTL_END;
1227     
1228     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1229
1230     _ASSERTE(refType != NULL);
1231
1232     TypeHandle typeHandle = refType->GetType();
1233
1234     FC_RETURN_BOOL(typeHandle.IsValueType());
1235 }
1236 FCIMPLEND;
1237
1238 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsInterface, ReflectClassBaseObject *pTypeUNSAFE)
1239 {
1240     CONTRACTL {
1241         FCALL_CHECK;
1242     }
1243     CONTRACTL_END;
1244     
1245     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1246
1247     _ASSERTE(refType != NULL);
1248
1249     TypeHandle typeHandle = refType->GetType();
1250
1251     FC_RETURN_BOOL(typeHandle.IsInterface());
1252 }
1253 FCIMPLEND;
1254
1255 BOOL 
1256 QCALLTYPE 
1257 RuntimeTypeHandle::IsVisible(
1258     EnregisteredTypeHandle pTypeHandle)
1259 {
1260     CONTRACTL
1261     {
1262         QCALL_CHECK;
1263     }
1264     CONTRACTL_END;
1265     
1266     BOOL fIsExternallyVisible = FALSE;
1267     
1268     BEGIN_QCALL;
1269     
1270     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1271
1272     _ASSERTE(!typeHandle.IsNull());
1273     
1274     fIsExternallyVisible = typeHandle.IsExternallyVisible();
1275     
1276     END_QCALL;
1277     
1278     return fIsExternallyVisible;
1279 } // RuntimeTypeHandle::IsVisible
1280
1281 // static
1282 BOOL QCALLTYPE RuntimeTypeHandle::IsSecurityCritical(EnregisteredTypeHandle pTypeHandle)
1283 {
1284     CONTRACTL
1285     {
1286         QCALL_CHECK;
1287         PRECONDITION(CheckPointer(pTypeHandle));
1288     }
1289     CONTRACTL_END;
1290
1291     BOOL fIsCritical = FALSE;
1292
1293     BEGIN_QCALL;
1294
1295     MethodTable *pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
1296     if (pMT != NULL)
1297     {
1298         fIsCritical = Security::IsTypeCritical(pMT);
1299     }
1300
1301     END_QCALL;
1302
1303     return fIsCritical;
1304 }
1305
1306 // static
1307 BOOL QCALLTYPE RuntimeTypeHandle::IsSecuritySafeCritical(EnregisteredTypeHandle pTypeHandle)
1308 {
1309     CONTRACTL
1310     {
1311         QCALL_CHECK;
1312         PRECONDITION(CheckPointer(pTypeHandle));
1313     }
1314     CONTRACTL_END;
1315
1316     BOOL fIsSafeCritical = FALSE;
1317
1318     BEGIN_QCALL;
1319
1320     MethodTable *pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
1321     if (pMT != NULL)
1322     {
1323         fIsSafeCritical = Security::IsTypeSafeCritical(pMT);
1324     }
1325
1326     END_QCALL;
1327
1328     return fIsSafeCritical;
1329 }
1330
1331 // static
1332 BOOL QCALLTYPE RuntimeTypeHandle::IsSecurityTransparent(EnregisteredTypeHandle pTypeHandle)
1333 {
1334     CONTRACTL
1335     {
1336         QCALL_CHECK;
1337         PRECONDITION(CheckPointer(pTypeHandle));
1338     }
1339     CONTRACTL_END;
1340
1341     BOOL fIsTransparent = TRUE;
1342
1343     BEGIN_QCALL;
1344
1345     MethodTable * pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
1346     if (pMT != NULL)
1347     {
1348         fIsTransparent = Security::IsTypeTransparent(pMT);
1349     }
1350     
1351     END_QCALL;
1352
1353     return fIsTransparent;
1354 }
1355     
1356 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::HasProxyAttribute, ReflectClassBaseObject *pTypeUNSAFE) {
1357     CONTRACTL {
1358         FCALL_CHECK;
1359     }
1360     CONTRACTL_END;
1361
1362     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1363
1364     if (refType == NULL)
1365         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1366
1367     TypeHandle typeHandle = refType->GetType();
1368     
1369     // TODO: Justify this
1370     if (typeHandle.IsGenericVariable())
1371         FC_RETURN_BOOL(FALSE);
1372         
1373     if (typeHandle.IsTypeDesc()) {
1374         if (!typeHandle.IsArray()) 
1375             FC_RETURN_BOOL(FALSE);
1376     }  
1377     
1378     MethodTable* pMT= typeHandle.GetMethodTable();
1379     
1380     if (!pMT) 
1381         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1382
1383     FC_RETURN_BOOL(pMT->GetClass()->HasRemotingProxyAttribute());
1384 }
1385 FCIMPLEND
1386
1387 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::IsComObject, ReflectClassBaseObject *pTypeUNSAFE, CLR_BOOL isGenericCOM) {
1388 #ifdef FEATURE_COMINTEROP
1389     CONTRACTL {
1390         FCALL_CHECK;
1391     }
1392     CONTRACTL_END;
1393     
1394     BOOL ret = FALSE;
1395
1396     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1397
1398     if (refType == NULL)
1399         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1400
1401     TypeHandle typeHandle = refType->GetType();
1402
1403     HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
1404     {
1405         if (isGenericCOM) 
1406             ret = IsComObjectClass(typeHandle);
1407         else
1408             ret = IsComWrapperClass(typeHandle);
1409     }
1410     HELPER_METHOD_FRAME_END();
1411
1412     FC_RETURN_BOOL(ret);
1413 #else
1414     CONTRACTL {
1415         DISABLED(NOTHROW);
1416         GC_NOTRIGGER;
1417         MODE_COOPERATIVE;
1418         PRECONDITION(CheckPointer(pTypeUNSAFE));
1419     }
1420     CONTRACTL_END;
1421     FCUnique(0x37);
1422     FC_RETURN_BOOL(FALSE);
1423 #endif
1424 }
1425 FCIMPLEND
1426
1427 FCIMPL1(LPCUTF8, RuntimeTypeHandle::GetUtf8Name, ReflectClassBaseObject* pTypeUNSAFE) {
1428     CONTRACTL {
1429         FCALL_CHECK;
1430     }
1431     CONTRACTL_END;
1432     
1433     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1434
1435     if (refType == NULL)
1436         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1437
1438     TypeHandle typeHandle = refType->GetType();
1439     INT32 tkTypeDef = mdTypeDefNil;
1440     LPCUTF8 szName = NULL;
1441
1442     if (typeHandle.IsGenericVariable())
1443         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1444         
1445     if (typeHandle.IsTypeDesc()) 
1446         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1447
1448     MethodTable* pMT= typeHandle.GetMethodTable();
1449     
1450     if (pMT == NULL)
1451         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1452
1453     tkTypeDef = (INT32)pMT->GetCl();
1454     
1455     if (IsNilToken(tkTypeDef))
1456         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1457     
1458     if (FAILED(pMT->GetMDImport()->GetNameOfTypeDef(tkTypeDef, &szName, NULL)))
1459     {
1460         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1461     }
1462     
1463     _ASSERTE(CheckPointer(szName, NULL_OK));
1464     
1465     return szName;
1466 }
1467 FCIMPLEND
1468
1469 FCIMPL1(INT32, RuntimeTypeHandle::GetToken, ReflectClassBaseObject *pTypeUNSAFE) {
1470     CONTRACTL {
1471         FCALL_CHECK;
1472     }
1473     CONTRACTL_END;
1474
1475     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1476
1477     if (refType == NULL)
1478         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1479
1480     TypeHandle typeHandle = refType->GetType();
1481
1482     if (typeHandle.IsTypeDesc()) 
1483     {
1484         if (typeHandle.IsGenericVariable())
1485         {
1486             INT32 tkTypeDef = typeHandle.AsGenericVariable()->GetToken();
1487         
1488             _ASSERTE(!IsNilToken(tkTypeDef) && TypeFromToken(tkTypeDef) == mdtGenericParam);
1489
1490             return tkTypeDef;
1491         }
1492         
1493         return mdTypeDefNil;
1494     }
1495
1496     return  (INT32)typeHandle.AsMethodTable()->GetCl();
1497 }
1498 FCIMPLEND
1499
1500 PVOID QCALLTYPE RuntimeTypeHandle::GetGCHandle(EnregisteredTypeHandle pTypeHandle, INT32 handleType)
1501 {
1502     QCALL_CONTRACT;
1503     
1504     OBJECTHANDLE objHandle = NULL;
1505
1506     BEGIN_QCALL;
1507     
1508     GCX_COOP();
1509
1510     TypeHandle th = TypeHandle::FromPtr(pTypeHandle);
1511     objHandle = th.GetDomain()->CreateTypedHandle(NULL, handleType);
1512     th.GetLoaderAllocator()->RegisterHandleForCleanup(objHandle);
1513
1514     END_QCALL;
1515
1516     return objHandle;
1517 }
1518
1519 void QCALLTYPE RuntimeTypeHandle::VerifyInterfaceIsImplemented(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pIFaceHandle)
1520 {
1521     QCALL_CONTRACT;
1522
1523     BEGIN_QCALL;
1524
1525     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1526     TypeHandle ifaceHandle = TypeHandle::FromPtr(pIFaceHandle);
1527
1528     if (typeHandle.IsGenericVariable())
1529         COMPlusThrow(kArgumentException, W("Arg_InvalidHandle"));
1530     
1531     if (typeHandle.IsTypeDesc()) {
1532         if (!typeHandle.IsArray())
1533             COMPlusThrow(kArgumentException, W("Arg_NotFoundIFace"));
1534     }
1535
1536     if (typeHandle.IsInterface())
1537         COMPlusThrow(kArgumentException, W("Argument_InterfaceMap"));
1538
1539     if (!ifaceHandle.IsInterface())
1540         COMPlusThrow(kArgumentException, W("Arg_MustBeInterface"));
1541
1542     // First try the cheap check, which amounts to iterating the interface map looking for
1543     // the ifaceHandle MethodTable.
1544     if (!typeHandle.GetMethodTable()->ImplementsInterface(ifaceHandle.AsMethodTable()))
1545     {   // If the cheap check fails, try the more expensive but complete check.
1546         if (!typeHandle.CanCastTo(ifaceHandle))
1547         {   // If the complete check fails, we're certain that this type
1548             // does not implement the interface specified.
1549         COMPlusThrow(kArgumentException, W("Arg_NotFoundIFace"));
1550         }
1551     }
1552
1553     END_QCALL;
1554 }
1555
1556 INT32 QCALLTYPE RuntimeTypeHandle::GetInterfaceMethodImplementationSlot(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pOwner, MethodDesc * pMD)
1557 {
1558     QCALL_CONTRACT;
1559
1560     INT32 slotNumber = -1;
1561
1562     BEGIN_QCALL;
1563
1564     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1565     TypeHandle thOwnerOfMD = TypeHandle::FromPtr(pOwner);
1566
1567         // Ok to have INVALID_SLOT in the case where abstract class does not implement an interface method.
1568         // This case can not be reproed using C# "implements" all interface methods
1569         // with at least an abstract method. b19897_GetInterfaceMap_Abstract.exe tests this case.
1570         //@TODO:STUBDISPATCH: Don't need to track down the implementation, just the declaration, and this can
1571         //@TODO:              be done faster - just need to make a function FindDispatchDecl.
1572         DispatchSlot slot(typeHandle.GetMethodTable()->FindDispatchSlotForInterfaceMD(thOwnerOfMD, pMD));
1573     if (!slot.IsNull())
1574             slotNumber = slot.GetMethodDesc()->GetSlot();
1575
1576     END_QCALL;
1577     
1578     return slotNumber;
1579     }
1580     
1581 void QCALLTYPE RuntimeTypeHandle::GetDefaultConstructor(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retMethod)
1582 {
1583     QCALL_CONTRACT;
1584
1585     BEGIN_QCALL;
1586     
1587     MethodDesc* pCtor = NULL;
1588     
1589     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1590
1591     if (!typeHandle.IsTypeDesc())
1592     {
1593         MethodTable* pMethodTable = typeHandle.AsMethodTable();
1594         if (pMethodTable->HasDefaultConstructor())
1595             pCtor = pMethodTable->GetDefaultConstructor();
1596     }
1597
1598     if (pCtor != NULL)
1599     {
1600         GCX_COOP();
1601         retMethod.Set(pCtor->GetStubMethodInfo());
1602     }
1603     END_QCALL;
1604
1605     return;
1606 }
1607
1608 FCIMPL1(ReflectMethodObject*, RuntimeTypeHandle::GetDeclaringMethod, ReflectClassBaseObject *pTypeUNSAFE) {
1609     CONTRACTL {
1610         FCALL_CHECK;
1611     }
1612     CONTRACTL_END;
1613     
1614     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1615
1616     if (refType == NULL)
1617         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1618
1619     TypeHandle typeHandle = refType->GetType();;
1620
1621     if (!typeHandle.IsTypeDesc())
1622         return NULL;
1623     
1624     TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();
1625     mdToken defToken = pGenericVariable->GetTypeOrMethodDef();
1626     if (TypeFromToken(defToken) != mdtMethodDef)
1627         return NULL;
1628
1629     REFLECTMETHODREF pRet = NULL;
1630     HELPER_METHOD_FRAME_BEGIN_RET_0();
1631     MethodDesc * pMD = pGenericVariable->LoadOwnerMethod();
1632     pMD->CheckRestore();
1633     pRet = pMD->GetStubMethodInfo();
1634     HELPER_METHOD_FRAME_END();
1635
1636     return (ReflectMethodObject*)OBJECTREFToObject(pRet);
1637 }
1638 FCIMPLEND
1639
1640 FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetDeclaringType, ReflectClassBaseObject *pTypeUNSAFE) {
1641     CONTRACTL {
1642         FCALL_CHECK;
1643     }
1644     CONTRACTL_END;
1645     
1646     TypeHandle retTypeHandle;
1647
1648     BOOL fThrowException = FALSE;
1649     LPCWSTR argName = W("Arg_InvalidHandle");
1650     RuntimeExceptionKind reKind = kArgumentNullException;
1651
1652     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1653
1654     if (refType == NULL)
1655         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1656
1657     TypeHandle typeHandle = refType->GetType();
1658
1659     MethodTable* pMT = NULL;
1660     mdTypeDef tkTypeDef = mdTokenNil;
1661
1662     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
1663     if (typeHandle.IsTypeDesc()) {
1664
1665         if (typeHandle.IsGenericVariable()) {
1666             TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();
1667             mdToken defToken = pGenericVariable->GetTypeOrMethodDef();
1668             
1669             // Try the fast way first (if the declaring type has been loaded already).
1670             if (TypeFromToken(defToken) == mdtMethodDef)
1671             {
1672                 MethodDesc * retMethod = pGenericVariable->GetModule()->LookupMethodDef(defToken);
1673                 if (retMethod != NULL)
1674                     retTypeHandle = retMethod->GetMethodTable();
1675             }
1676             else
1677             {
1678                 retTypeHandle = pGenericVariable->GetModule()->LookupTypeDef(defToken);
1679             }
1680
1681             if (!retTypeHandle.IsNull() && retTypeHandle.IsFullyLoaded())
1682                 goto Exit;
1683
1684             // OK, need to go the slow way and load the type first.
1685             HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
1686             {
1687                 if (TypeFromToken(defToken) == mdtMethodDef)
1688                 {
1689                     retTypeHandle = pGenericVariable->LoadOwnerMethod()->GetMethodTable();
1690                 }
1691                 else
1692                 {
1693                     retTypeHandle = pGenericVariable->LoadOwnerType();
1694                 }
1695                 retTypeHandle.CheckRestore();
1696             }
1697             HELPER_METHOD_FRAME_END();
1698             goto Exit;
1699         }
1700         if (!typeHandle.IsArray())
1701         {
1702             retTypeHandle = TypeHandle();
1703             goto Exit;
1704         }
1705     }
1706     
1707     pMT = typeHandle.GetMethodTable();
1708
1709     if (pMT == NULL) 
1710     {
1711         fThrowException = TRUE;
1712         goto Exit;
1713     }
1714
1715     if(!pMT->GetClass()->IsNested())
1716     {
1717         retTypeHandle = TypeHandle();
1718         goto Exit;
1719     }
1720
1721     tkTypeDef = pMT->GetCl();
1722     
1723     if (FAILED(typeHandle.GetModule()->GetMDImport()->GetNestedClassProps(tkTypeDef, &tkTypeDef)))
1724     {
1725         fThrowException = TRUE;
1726         reKind = kBadImageFormatException;
1727         argName = NULL;
1728         goto Exit;
1729     }
1730     
1731     // Try the fast way first (if the declaring type has been loaded already).
1732     retTypeHandle = typeHandle.GetModule()->LookupTypeDef(tkTypeDef);
1733     if (retTypeHandle.IsNull())
1734     { 
1735          // OK, need to go the slow way and load the type first.
1736         HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
1737         {
1738             retTypeHandle = ClassLoader::LoadTypeDefThrowing(typeHandle.GetModule(), tkTypeDef, 
1739                                                              ClassLoader::ThrowIfNotFound, 
1740                                                              ClassLoader::PermitUninstDefOrRef);
1741         }
1742         HELPER_METHOD_FRAME_END();
1743     }
1744 Exit:
1745
1746     END_SO_INTOLERANT_CODE;
1747
1748     if (fThrowException)
1749     {
1750         FCThrowRes(reKind, argName);
1751     }
1752
1753     RETURN_CLASS_OBJECT(retTypeHandle, refType);
1754   }
1755 FCIMPLEND
1756
1757 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::CanCastTo, ReflectClassBaseObject *pTypeUNSAFE, ReflectClassBaseObject *pTargetUNSAFE) {
1758     CONTRACTL {
1759         FCALL_CHECK;
1760     }
1761     CONTRACTL_END;
1762     
1763     
1764     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1765     REFLECTCLASSBASEREF refTarget = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTargetUNSAFE);
1766
1767     if ((refType == NULL) || (refTarget == NULL)) 
1768         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1769
1770     TypeHandle fromHandle = refType->GetType();
1771     TypeHandle toHandle = refTarget->GetType();
1772
1773     BOOL iRetVal = 0;
1774
1775     TypeHandle::CastResult r = fromHandle.CanCastToNoGC(toHandle);
1776     if (r == TypeHandle::MaybeCast)
1777     {
1778         HELPER_METHOD_FRAME_BEGIN_RET_2(refType, refTarget);
1779         iRetVal = fromHandle.CanCastTo(toHandle);
1780         HELPER_METHOD_FRAME_END();
1781     }
1782     else
1783     {
1784         iRetVal = (r == TypeHandle::CanCast);
1785     }
1786
1787     // We allow T to be cast to Nullable<T>
1788     if (!iRetVal && Nullable::IsNullableType(toHandle) && !fromHandle.IsTypeDesc())
1789     {
1790         HELPER_METHOD_FRAME_BEGIN_RET_2(refType, refTarget);
1791         if (Nullable::IsNullableForType(toHandle, fromHandle.AsMethodTable())) 
1792         {
1793             iRetVal = TRUE;
1794         }
1795         HELPER_METHOD_FRAME_END();
1796     }
1797         
1798     FC_RETURN_BOOL(iRetVal);
1799 }
1800 FCIMPLEND
1801
1802 void QCALLTYPE RuntimeTypeHandle::GetTypeByNameUsingCARules(LPCWSTR pwzClassName, QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retType)
1803 {
1804     QCALL_CONTRACT;
1805     
1806     TypeHandle typeHandle;
1807
1808     BEGIN_QCALL;
1809         
1810     if (!pwzClassName)
1811         COMPlusThrowArgumentNull(W("className"),W("ArgumentNull_String"));
1812
1813     typeHandle = TypeName::GetTypeUsingCASearchRules(pwzClassName, pModule->GetAssembly());
1814
1815     GCX_COOP();
1816     retType.Set(typeHandle.GetManagedClassObject());
1817
1818     END_QCALL;
1819
1820     return;
1821 }
1822
1823 void QCALLTYPE RuntimeTypeHandle::GetTypeByName(LPCWSTR pwzClassName, BOOL bThrowOnError, BOOL bIgnoreCase, BOOL bReflectionOnly,
1824                                                 QCall::StackCrawlMarkHandle pStackMark, 
1825                                                 ICLRPrivBinder * pPrivHostBinder,
1826                                                 BOOL bLoadTypeFromPartialNameHack, QCall::ObjectHandleOnStack retType,
1827                                                 QCall::ObjectHandleOnStack keepAlive)
1828 {
1829     QCALL_CONTRACT;
1830     
1831     TypeHandle typeHandle;
1832     
1833     BEGIN_QCALL;
1834
1835     if (!pwzClassName)
1836             COMPlusThrowArgumentNull(W("className"),W("ArgumentNull_String"));
1837
1838     {
1839         typeHandle = TypeName::GetTypeManaged(pwzClassName, NULL, bThrowOnError, bIgnoreCase, bReflectionOnly, /*bProhibitAsmQualifiedName =*/ FALSE, pStackMark,
1840                                               bLoadTypeFromPartialNameHack, (OBJECTREF*)keepAlive.m_ppObject,
1841                                               pPrivHostBinder);
1842     }
1843
1844     if (!typeHandle.IsNull())
1845     {
1846         GCX_COOP();
1847         retType.Set(typeHandle.GetManagedClassObject());
1848     }
1849
1850     END_QCALL;
1851
1852     return;
1853 }
1854
1855 FCIMPL6(FC_BOOL_RET, RuntimeTypeHandle::SatisfiesConstraints, PTR_ReflectClassBaseObject pParamTypeUNSAFE, TypeHandle *typeContextArgs, INT32 typeContextCount, TypeHandle *methodContextArgs, INT32 methodContextCount, PTR_ReflectClassBaseObject pArgumentTypeUNSAFE);
1856 {
1857     CONTRACTL {
1858         FCALL_CHECK;
1859         PRECONDITION(CheckPointer(typeContextArgs, NULL_OK));
1860         PRECONDITION(CheckPointer(methodContextArgs, NULL_OK));
1861     }
1862     CONTRACTL_END;
1863     
1864     REFLECTCLASSBASEREF refParamType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pParamTypeUNSAFE);
1865     REFLECTCLASSBASEREF refArgumentType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pArgumentTypeUNSAFE);
1866
1867     TypeHandle thGenericParameter = refParamType->GetType();
1868     TypeHandle thGenericArgument = refArgumentType->GetType();
1869     BOOL bResult = FALSE; 
1870     SigTypeContext typeContext;
1871
1872     Instantiation classInst;
1873     Instantiation methodInst;
1874
1875     if (typeContextArgs != NULL)
1876     {
1877         classInst = Instantiation(typeContextArgs, typeContextCount);
1878     }
1879     
1880     if (methodContextArgs != NULL)
1881     {
1882         methodInst = Instantiation(methodContextArgs, methodContextCount);
1883     }
1884
1885     SigTypeContext::InitTypeContext(classInst, methodInst, &typeContext);
1886
1887     HELPER_METHOD_FRAME_BEGIN_RET_2(refParamType, refArgumentType);
1888     {
1889         bResult = thGenericParameter.AsGenericVariable()->SatisfiesConstraints(&typeContext, thGenericArgument);
1890     }
1891     HELPER_METHOD_FRAME_END();
1892
1893     FC_RETURN_BOOL(bResult);      
1894 }
1895 FCIMPLEND
1896
1897 void QCALLTYPE RuntimeTypeHandle::GetInstantiation(EnregisteredTypeHandle pType, QCall::ObjectHandleOnStack retTypes, BOOL fAsRuntimeTypeArray)
1898 {
1899     QCALL_CONTRACT;
1900
1901     BEGIN_QCALL;
1902
1903     TypeHandle typeHandle = TypeHandle::FromPtr(pType);
1904     Instantiation inst = typeHandle.GetInstantiation();
1905     GCX_COOP();
1906     retTypes.Set(CopyRuntimeTypeHandles(NULL, inst.GetRawArgs(), inst.GetNumArgs(), fAsRuntimeTypeArray ? CLASS__CLASS : CLASS__TYPE));
1907     END_QCALL;
1908
1909     return;
1910 }
1911
1912 void QCALLTYPE RuntimeTypeHandle::MakeArray(EnregisteredTypeHandle pTypeHandle, INT32 rank, QCall::ObjectHandleOnStack retType)
1913 {
1914     QCALL_CONTRACT;
1915
1916     TypeHandle arrayHandle;
1917     
1918     BEGIN_QCALL;
1919     arrayHandle = TypeHandle::FromPtr(pTypeHandle).MakeArray(rank);
1920     GCX_COOP();
1921     retType.Set(arrayHandle.GetManagedClassObject());
1922     END_QCALL;
1923     
1924     return;
1925 }
1926
1927 void QCALLTYPE RuntimeTypeHandle::MakeSZArray(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
1928 {
1929     QCALL_CONTRACT;
1930     
1931     TypeHandle arrayHandle;
1932     
1933     BEGIN_QCALL;
1934     arrayHandle = TypeHandle::FromPtr(pTypeHandle).MakeSZArray();
1935     GCX_COOP();
1936     retType.Set(arrayHandle.GetManagedClassObject());
1937     END_QCALL;
1938
1939     return;
1940 }
1941
1942 void QCALLTYPE RuntimeTypeHandle::MakePointer(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
1943 {
1944     QCALL_CONTRACT;
1945     
1946     TypeHandle pointerHandle;
1947     
1948     BEGIN_QCALL;
1949     pointerHandle = TypeHandle::FromPtr(pTypeHandle).MakePointer();
1950     GCX_COOP();
1951     retType.Set(pointerHandle.GetManagedClassObject());
1952     END_QCALL;
1953     
1954     return;
1955 }
1956
1957 void QCALLTYPE RuntimeTypeHandle::MakeByRef(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
1958 {
1959     QCALL_CONTRACT;
1960     
1961     TypeHandle byRefHandle;
1962     
1963     BEGIN_QCALL;
1964     byRefHandle = TypeHandle::FromPtr(pTypeHandle).MakeByRef();
1965     GCX_COOP();
1966     retType.Set(byRefHandle.GetManagedClassObject());
1967     END_QCALL;
1968     
1969     return;
1970 }
1971
1972 BOOL QCALLTYPE RuntimeTypeHandle::IsCollectible(EnregisteredTypeHandle pTypeHandle)
1973 {
1974     QCALL_CONTRACT;
1975
1976     BOOL retVal = FALSE;
1977
1978     BEGIN_QCALL;
1979     retVal = TypeHandle::FromPtr(pTypeHandle).GetLoaderAllocator()->IsCollectible();
1980     END_QCALL;
1981
1982     return retVal;
1983 }
1984     
1985 void QCALLTYPE RuntimeTypeHandle::Instantiate(EnregisteredTypeHandle pTypeHandle, TypeHandle * pInstArray, INT32 cInstArray, QCall::ObjectHandleOnStack retType)
1986 {
1987     QCALL_CONTRACT;
1988     
1989     TypeHandle type;
1990
1991     BEGIN_QCALL;
1992     type = TypeHandle::FromPtr(pTypeHandle).Instantiate(Instantiation(pInstArray, cInstArray));
1993     GCX_COOP();
1994     retType.Set(type.GetManagedClassObject());
1995     END_QCALL;
1996
1997     return;
1998 }
1999
2000 void QCALLTYPE RuntimeTypeHandle::GetGenericTypeDefinition(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
2001 {
2002     QCALL_CONTRACT;
2003     
2004     TypeHandle typeDef;
2005     
2006     BEGIN_QCALL;
2007     
2008     TypeHandle genericType = TypeHandle::FromPtr(pTypeHandle);
2009
2010     typeDef = ClassLoader::LoadTypeDefThrowing(genericType.GetModule(), 
2011                                                        genericType.GetMethodTable()->GetCl(),
2012                                                        ClassLoader::ThrowIfNotFound,
2013                                                        ClassLoader::PermitUninstDefOrRef);
2014
2015     GCX_COOP();
2016     retType.Set(typeDef.GetManagedClassObject());
2017
2018     END_QCALL;
2019     
2020     return;
2021 }
2022
2023 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::CompareCanonicalHandles, ReflectClassBaseObject *pLeftUNSAFE, ReflectClassBaseObject *pRightUNSAFE)
2024 {
2025     FCALL_CONTRACT;
2026     
2027     REFLECTCLASSBASEREF refLeft = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pLeftUNSAFE);
2028     REFLECTCLASSBASEREF refRight = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pRightUNSAFE);
2029
2030     if ((refLeft == NULL) || (refRight == NULL))
2031         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2032
2033     FC_RETURN_BOOL(refLeft->GetType().GetCanonicalMethodTable() == refRight->GetType().GetCanonicalMethodTable());
2034 }
2035 FCIMPLEND
2036
2037 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::HasInstantiation, PTR_ReflectClassBaseObject pTypeUNSAFE)
2038 {
2039     FCALL_CONTRACT;       
2040     
2041     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2042
2043     if (refType == NULL)
2044         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2045
2046     FC_RETURN_BOOL(refType->GetType().HasInstantiation());
2047 }
2048 FCIMPLEND
2049
2050 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsGenericTypeDefinition, PTR_ReflectClassBaseObject pTypeUNSAFE)
2051 {
2052     FCALL_CONTRACT;
2053     
2054     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2055
2056     if (refType == NULL)
2057         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2058
2059     FC_RETURN_BOOL(refType->GetType().IsGenericTypeDefinition());
2060 }
2061 FCIMPLEND
2062
2063 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsGenericVariable, PTR_ReflectClassBaseObject pTypeUNSAFE)
2064 {
2065     FCALL_CONTRACT;
2066     
2067     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2068
2069     if (refType == NULL)
2070         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2071
2072     FC_RETURN_BOOL(refType->GetType().IsGenericVariable());
2073 }
2074 FCIMPLEND
2075
2076 FCIMPL1(INT32, RuntimeTypeHandle::GetGenericVariableIndex, PTR_ReflectClassBaseObject pTypeUNSAFE)
2077 {
2078     FCALL_CONTRACT;
2079     
2080     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2081
2082     if (refType == NULL)
2083         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2084
2085     return (INT32)refType->GetType().AsGenericVariable()->GetIndex();
2086 }
2087 FCIMPLEND
2088
2089 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::ContainsGenericVariables, PTR_ReflectClassBaseObject pTypeUNSAFE)
2090 {
2091     FCALL_CONTRACT;
2092
2093     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2094
2095     if (refType == NULL)
2096         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2097
2098     FC_RETURN_BOOL(refType->GetType().ContainsGenericVariables());
2099 }
2100 FCIMPLEND
2101
2102 FCIMPL1(IMDInternalImport*, RuntimeTypeHandle::GetMetadataImport, ReflectClassBaseObject * pTypeUNSAFE)
2103 {
2104     FCALL_CONTRACT;
2105
2106     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2107
2108     if (refType == NULL)
2109         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2110
2111     Module *pModule = refType->GetType().GetModule();
2112
2113     return pModule->GetMDImport();
2114 }
2115 FCIMPLEND
2116
2117
2118 //***********************************************************************************
2119 //***********************************************************************************
2120 //***********************************************************************************
2121
2122 void * QCALLTYPE RuntimeMethodHandle::GetFunctionPointer(MethodDesc * pMethod)
2123 {
2124     QCALL_CONTRACT;
2125         
2126     void* funcPtr = 0;
2127     
2128     BEGIN_QCALL;
2129
2130     funcPtr = (void*)pMethod->GetMultiCallableAddrOfCode();
2131
2132     END_QCALL;
2133
2134     return funcPtr;
2135 }
2136     
2137 FCIMPL1(LPCUTF8, RuntimeMethodHandle::GetUtf8Name, MethodDesc *pMethod) {
2138     CONTRACTL {
2139         FCALL_CHECK;
2140     }
2141     CONTRACTL_END;
2142     
2143     LPCUTF8 szName = NULL;
2144     
2145     if (!pMethod)
2146         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2147            
2148     szName = pMethod->GetName();
2149
2150     _ASSERTE(CheckPointer(szName, NULL_OK));
2151     
2152     return szName;
2153 }
2154 FCIMPLEND
2155
2156 FCIMPL2(FC_BOOL_RET, RuntimeMethodHandle::MatchesNameHash, MethodDesc * pMethod, ULONG hash)
2157 {
2158     FCALL_CONTRACT;
2159
2160     FC_RETURN_BOOL(pMethod->MightHaveName(hash));
2161 }
2162 FCIMPLEND
2163
2164 FCIMPL1(StringObject*, RuntimeMethodHandle::GetName, MethodDesc *pMethod) {
2165     CONTRACTL {
2166         FCALL_CHECK;
2167     }
2168     CONTRACTL_END;
2169         
2170     if (!pMethod)
2171         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2172         
2173     STRINGREF refName = NULL;
2174
2175     HELPER_METHOD_FRAME_BEGIN_RET_0();
2176     refName = StringObject::NewString(pMethod->GetName());
2177     HELPER_METHOD_FRAME_END();            
2178     
2179     return (StringObject*)OBJECTREFToObject(refName);
2180 }
2181 FCIMPLEND
2182
2183 FCIMPL1(INT32, RuntimeMethodHandle::GetAttributes, MethodDesc *pMethod) {
2184     CONTRACTL {
2185         FCALL_CHECK;
2186     }
2187     CONTRACTL_END;
2188     
2189     if (!pMethod)
2190         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2191
2192     INT32 retVal = 0;        
2193     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
2194     retVal = (INT32)pMethod->GetAttrs();
2195     END_SO_INTOLERANT_CODE;
2196     return retVal;
2197 }
2198 FCIMPLEND
2199
2200 FCIMPL1(INT32, RuntimeMethodHandle::GetImplAttributes, ReflectMethodObject *pMethodUNSAFE) {
2201     CONTRACTL {
2202         FCALL_CHECK;
2203     }
2204     CONTRACTL_END;
2205     
2206     if (!pMethodUNSAFE)
2207         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2208
2209     MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
2210     INT32 attributes = 0;
2211
2212     if (IsNilToken(pMethod->GetMemberDef()))
2213         return attributes;
2214     
2215     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
2216     {
2217         attributes = (INT32)pMethod->GetImplAttrs();
2218     }
2219     END_SO_INTOLERANT_CODE;
2220
2221     return attributes;
2222 }
2223 FCIMPLEND
2224     
2225
2226 FCIMPL1(ReflectClassBaseObject*, RuntimeMethodHandle::GetDeclaringType, MethodDesc *pMethod) {
2227     CONTRACTL {
2228         FCALL_CHECK;
2229         PRECONDITION(CheckPointer(pMethod));
2230     }
2231     CONTRACTL_END;
2232     
2233     if (!pMethod)
2234         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2235         
2236     MethodTable *pMT = pMethod->GetMethodTable();
2237     TypeHandle declType(pMT);
2238     if (pMT->IsArray()) 
2239     {
2240         HELPER_METHOD_FRAME_BEGIN_RET_0();   
2241         
2242         // Load the TypeDesc for the array type.  Note the returned type is approximate, i.e.
2243         // if shared between reference array types then we will get object[] back.
2244         DWORD rank = pMT->GetRank();
2245         TypeHandle elemType = pMT->GetApproxArrayElementTypeHandle();
2246         declType = ClassLoader::LoadArrayTypeThrowing(elemType, pMT->GetInternalCorElementType(), rank);
2247         HELPER_METHOD_FRAME_END();            
2248     }
2249     RETURN_CLASS_OBJECT(declType, NULL);
2250 }
2251 FCIMPLEND
2252
2253 FCIMPL1(INT32, RuntimeMethodHandle::GetSlot, MethodDesc *pMethod) {
2254     CONTRACTL {
2255         FCALL_CHECK;
2256     }
2257     CONTRACTL_END;
2258     
2259     if (!pMethod)
2260         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2261         
2262     return (INT32)pMethod->GetSlot();
2263 }
2264 FCIMPLEND
2265
2266 FCIMPL3(Object *, SignatureNative::GetCustomModifiers, SignatureNative* pSignatureUNSAFE, 
2267     INT32 parameter, CLR_BOOL fRequired)
2268 {   
2269     CONTRACTL {
2270         FCALL_CHECK;
2271     }
2272     CONTRACTL_END;
2273
2274     struct 
2275     {
2276         SIGNATURENATIVEREF pSig;
2277         PTRARRAYREF retVal;
2278     } gc;
2279
2280     gc.pSig = (SIGNATURENATIVEREF)pSignatureUNSAFE;
2281     gc.retVal = NULL;
2282
2283     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
2284     {
2285         
2286         BYTE callConv = *(BYTE*)gc.pSig->GetCorSig();
2287         SigTypeContext typeContext;
2288         gc.pSig->GetTypeContext(&typeContext);
2289         MetaSig sig(gc.pSig->GetCorSig(), 
2290                     gc.pSig->GetCorSigSize(),
2291                     gc.pSig->GetModule(), 
2292                     &typeContext,
2293                     (callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_CS_CALLCONV_FIELD ? MetaSig::sigField : MetaSig::sigMember);
2294         _ASSERTE(callConv == sig.GetCallingConventionInfo());                 
2295
2296         SigPointer argument(NULL, 0);
2297
2298         PRECONDITION(sig.GetCallingConvention() != IMAGE_CEE_CS_CALLCONV_FIELD || parameter == 1);
2299
2300         if (parameter == 0) 
2301         {
2302             argument = sig.GetReturnProps();
2303         }
2304         else
2305         {
2306             for(INT32 i = 0; i < parameter; i++)
2307                 sig.NextArg();
2308
2309             argument = sig.GetArgProps();
2310         }
2311         
2312         //if (parameter < 0 || parameter > (INT32)sig.NumFixedArgs())
2313         //    FCThrowResVoid(kArgumentNullException, W("Arg_ArgumentOutOfRangeException")); 
2314         
2315         SigPointer sp = argument;
2316         Module* pModule = sig.GetModule();
2317         INT32 cMods = 0;
2318         CorElementType cmodType;
2319
2320         CorElementType cmodTypeExpected = fRequired ? ELEMENT_TYPE_CMOD_REQD : ELEMENT_TYPE_CMOD_OPT;
2321         
2322         // Discover the number of required and optional custom modifiers.   
2323         while(TRUE)
2324         {
2325             BYTE data;
2326             IfFailThrow(sp.GetByte(&data));
2327             cmodType = (CorElementType)data;
2328             
2329             if (cmodType == ELEMENT_TYPE_CMOD_REQD || cmodType == ELEMENT_TYPE_CMOD_OPT)
2330             {
2331                 if (cmodType == cmodTypeExpected)
2332                 {
2333                     cMods ++;
2334                 }
2335             }        
2336             else if (cmodType != ELEMENT_TYPE_SENTINEL) 
2337             {
2338                 break;        
2339             }
2340             
2341             IfFailThrow(sp.GetToken(NULL));
2342         }
2343
2344         // Reset sp and populate the arrays for the required and optional custom 
2345         // modifiers now that we know how long they should be. 
2346         sp = argument;
2347
2348         MethodTable *pMT = MscorlibBinder::GetClass(CLASS__TYPE);
2349         TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pMT), ELEMENT_TYPE_SZARRAY);
2350
2351         gc.retVal = (PTRARRAYREF) AllocateArrayEx(arrayHandle, &cMods, 1);
2352
2353         while(cMods != 0)
2354         {
2355             BYTE data;
2356             IfFailThrow(sp.GetByte(&data));
2357             cmodType = (CorElementType)data;
2358
2359             mdToken token;
2360             IfFailThrow(sp.GetToken(&token));
2361
2362             if (cmodType == cmodTypeExpected)
2363             {
2364                 TypeHandle th = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, token, 
2365                                                                             &typeContext,
2366                                                                             ClassLoader::ThrowIfNotFound, 
2367                                                                             ClassLoader::FailIfUninstDefOrRef);        
2368         
2369                 OBJECTREF refType = th.GetManagedClassObject();
2370                 gc.retVal->SetAt(--cMods, refType);
2371             }
2372         }    
2373     }  
2374     HELPER_METHOD_FRAME_END();
2375
2376     return OBJECTREFToObject(gc.retVal);
2377 }
2378 FCIMPLEND
2379
2380 FCIMPL1(INT32, RuntimeMethodHandle::GetMethodDef, ReflectMethodObject *pMethodUNSAFE) {
2381     CONTRACTL {
2382         FCALL_CHECK;
2383     }
2384     CONTRACTL_END;
2385     
2386     if (!pMethodUNSAFE)
2387         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2388
2389     MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
2390
2391     if (pMethod->HasMethodInstantiation())
2392     {
2393         HELPER_METHOD_FRAME_BEGIN_RET_1(pMethodUNSAFE);
2394         {         
2395             pMethod = pMethod->StripMethodInstantiation();
2396         }
2397         HELPER_METHOD_FRAME_END();
2398     }
2399
2400     INT32 tkMethodDef = (INT32)pMethod->GetMemberDef();
2401     _ASSERTE(TypeFromToken(tkMethodDef) == mdtMethodDef);
2402     
2403     if (IsNilToken(tkMethodDef) || TypeFromToken(tkMethodDef) != mdtMethodDef)
2404         return mdMethodDefNil;
2405     
2406     return tkMethodDef;
2407 }
2408 FCIMPLEND
2409
2410 FCIMPL6(void, SignatureNative::GetSignature,
2411     SignatureNative* pSignatureNativeUNSAFE, 
2412     PCCOR_SIGNATURE pCorSig, DWORD cCorSig,
2413     FieldDesc *pFieldDesc, ReflectMethodObject *pMethodUNSAFE, ReflectClassBaseObject *pDeclaringTypeUNSAFE) {
2414     CONTRACTL {
2415         FCALL_CHECK;
2416         PRECONDITION(pDeclaringTypeUNSAFE || pMethodUNSAFE->GetMethod()->IsDynamicMethod());
2417         PRECONDITION(CheckPointer(pCorSig, NULL_OK));
2418         PRECONDITION(CheckPointer(pMethodUNSAFE, NULL_OK));
2419         PRECONDITION(CheckPointer(pFieldDesc, NULL_OK));
2420     }
2421     CONTRACTL_END;
2422
2423     struct
2424     {
2425         REFLECTCLASSBASEREF refDeclaringType;
2426         REFLECTMETHODREF refMethod;
2427         SIGNATURENATIVEREF pSig;
2428     } gc;
2429
2430     gc.refDeclaringType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
2431     gc.refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
2432     gc.pSig = (SIGNATURENATIVEREF)pSignatureNativeUNSAFE;
2433
2434     MethodDesc *pMethod;
2435     TypeHandle declType;
2436
2437     if (gc.refDeclaringType == NULL)
2438     {
2439         // for dynamic method, see precondition
2440         pMethod = gc.refMethod->GetMethod();
2441         declType = pMethod->GetMethodTable();
2442     }
2443     else
2444     {
2445         pMethod = gc.refMethod != NULL ? gc.refMethod->GetMethod() : NULL;
2446         declType = gc.refDeclaringType->GetType();
2447     }
2448
2449     HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
2450     {        
2451         Module* pModule = declType.GetModule();
2452         
2453         if (pMethod)
2454         {
2455             pMethod->GetSig(&pCorSig, &cCorSig);
2456             if (pMethod->GetClassification() == mcInstantiated)
2457             {
2458                 LoaderAllocator *pLoaderAllocator = pMethod->GetLoaderAllocator();
2459                 if (pLoaderAllocator->IsCollectible())
2460                     gc.pSig->SetKeepAlive(pLoaderAllocator->GetExposedObject());
2461             }
2462         }
2463         else if (pFieldDesc)
2464             pFieldDesc->GetSig(&pCorSig, &cCorSig);
2465         
2466         gc.pSig->m_sig = pCorSig;    
2467         gc.pSig->m_cSig = cCorSig;    
2468         gc.pSig->m_pMethod = pMethod;    
2469
2470         REFLECTCLASSBASEREF refDeclType = (REFLECTCLASSBASEREF)declType.GetManagedClassObject();
2471         gc.pSig->SetDeclaringType(refDeclType);
2472
2473         PREFIX_ASSUME(pCorSig!= NULL);
2474         BYTE callConv = *(BYTE*)pCorSig;
2475         SigTypeContext typeContext;
2476         if (pMethod)
2477             SigTypeContext::InitTypeContext(
2478                 pMethod, declType.GetClassOrArrayInstantiation(), pMethod->LoadMethodInstantiation(), &typeContext);
2479         else
2480             SigTypeContext::InitTypeContext(declType, &typeContext);
2481         MetaSig msig(pCorSig, cCorSig, pModule, &typeContext,
2482             (callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_CS_CALLCONV_FIELD ? MetaSig::sigField : MetaSig::sigMember);
2483
2484         if (callConv == IMAGE_CEE_CS_CALLCONV_FIELD)
2485         {            
2486             msig.NextArgNormalized();
2487
2488             OBJECTREF refRetType = msig.GetLastTypeHandleThrowing().GetManagedClassObject();
2489             gc.pSig->SetReturnType(refRetType);
2490         }
2491         else
2492         {
2493             gc.pSig->SetCallingConvention(msig.GetCallingConventionInfo());
2494
2495             OBJECTREF refRetType = msig.GetRetTypeHandleThrowing().GetManagedClassObject();
2496             gc.pSig->SetReturnType(refRetType);
2497
2498             INT32 nArgs = msig.NumFixedArgs();
2499             TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pRuntimeTypeClass), ELEMENT_TYPE_SZARRAY);
2500
2501             PTRARRAYREF ptrArrayarguments = (PTRARRAYREF) AllocateArrayEx(arrayHandle, &nArgs, 1);
2502             gc.pSig->SetArgumentArray(ptrArrayarguments);
2503
2504             for (INT32 i = 0; i < nArgs; i++) 
2505             {
2506                 msig.NextArg();
2507
2508                 OBJECTREF refArgType = msig.GetLastTypeHandleThrowing().GetManagedClassObject();
2509                 gc.pSig->SetArgument(i, refArgType);
2510             }
2511
2512             _ASSERTE(gc.pSig->m_returnType != NULL);
2513         }
2514     }
2515     HELPER_METHOD_FRAME_END();
2516 }
2517 FCIMPLEND
2518
2519 FCIMPL2(FC_BOOL_RET, SignatureNative::CompareSig, SignatureNative* pLhsUNSAFE, SignatureNative* pRhsUNSAFE)
2520 {
2521     FCALL_CONTRACT;
2522     
2523     INT32 ret = 0;
2524
2525     struct
2526     {
2527         SIGNATURENATIVEREF pLhs;
2528         SIGNATURENATIVEREF pRhs;
2529     } gc;
2530
2531     gc.pLhs = (SIGNATURENATIVEREF)pLhsUNSAFE;
2532     gc.pRhs = (SIGNATURENATIVEREF)pRhsUNSAFE;
2533
2534     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
2535     {
2536         ret = MetaSig::CompareMethodSigs(
2537             gc.pLhs->GetCorSig(), gc.pLhs->GetCorSigSize(), gc.pLhs->GetModule(), NULL, 
2538             gc.pRhs->GetCorSig(), gc.pRhs->GetCorSigSize(), gc.pRhs->GetModule(), NULL);    
2539     }
2540     HELPER_METHOD_FRAME_END();
2541     FC_RETURN_BOOL(ret);
2542 }
2543 FCIMPLEND
2544
2545 void QCALLTYPE RuntimeMethodHandle::GetMethodInstantiation(MethodDesc * pMethod, QCall::ObjectHandleOnStack retTypes, BOOL fAsRuntimeTypeArray)
2546 {
2547     QCALL_CONTRACT;
2548             
2549     BEGIN_QCALL;
2550     Instantiation inst = pMethod->LoadMethodInstantiation();
2551
2552     GCX_COOP();
2553     retTypes.Set(CopyRuntimeTypeHandles(NULL, inst.GetRawArgs(), inst.GetNumArgs(), fAsRuntimeTypeArray ? CLASS__CLASS : CLASS__TYPE));
2554     END_QCALL;
2555
2556     return;
2557 }
2558     
2559 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::HasMethodInstantiation, MethodDesc * pMethod)
2560 {
2561     FCALL_CONTRACT;
2562
2563     FC_RETURN_BOOL(pMethod->HasMethodInstantiation());
2564 }
2565 FCIMPLEND
2566
2567 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsGenericMethodDefinition, MethodDesc * pMethod)
2568 {
2569     FCALL_CONTRACT;
2570
2571     FC_RETURN_BOOL(pMethod->IsGenericMethodDefinition());
2572 }
2573 FCIMPLEND
2574
2575 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsDynamicMethod, MethodDesc * pMethod)
2576 {
2577     FCALL_CONTRACT;
2578
2579     FC_RETURN_BOOL(pMethod->IsNoMetadata());
2580 }
2581 FCIMPLEND
2582
2583 FCIMPL1(Object*, RuntimeMethodHandle::GetResolver, MethodDesc * pMethod)
2584 {
2585     FCALL_CONTRACT;
2586
2587     if (!pMethod)
2588         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2589
2590     OBJECTREF resolver = NULL;
2591     if (pMethod->IsLCGMethod())
2592     {
2593         resolver = pMethod->AsDynamicMethodDesc()->GetLCGMethodResolver()->GetManagedResolver();
2594     }
2595     return OBJECTREFToObject(resolver);
2596 }
2597 FCIMPLEND
2598
2599 void QCALLTYPE RuntimeMethodHandle::Destroy(MethodDesc * pMethod)
2600 {
2601     QCALL_CONTRACT;
2602
2603     BEGIN_QCALL;
2604
2605     if (pMethod == NULL)
2606         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
2607     
2608     DynamicMethodDesc* pDynamicMethodDesc = pMethod->AsDynamicMethodDesc();
2609
2610     GCX_COOP();
2611
2612     // Destroy should be called only if the managed part is gone.
2613     _ASSERTE(OBJECTREFToObject(pDynamicMethodDesc->GetLCGMethodResolver()->GetManagedResolver()) == NULL);
2614
2615     // Fire Unload Dynamic Method Event here
2616     ETW::MethodLog::DynamicMethodDestroyed(pMethod);
2617
2618     BEGIN_PIN_PROFILER(CORProfilerIsMonitoringDynamicFunctionUnloads());
2619     g_profControlBlock.pProfInterface->DynamicMethodUnloaded((FunctionID)pMethod);
2620     END_PIN_PROFILER();
2621
2622     pDynamicMethodDesc->Destroy();
2623
2624     END_QCALL;
2625     }
2626     
2627 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsTypicalMethodDefinition, ReflectMethodObject *pMethodUNSAFE)
2628 {
2629     FCALL_CONTRACT;
2630
2631     if (!pMethodUNSAFE)
2632         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2633
2634     MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
2635
2636     FC_RETURN_BOOL(pMethod->IsTypicalMethodDefinition());
2637 }
2638 FCIMPLEND
2639     
2640 void QCALLTYPE RuntimeMethodHandle::GetTypicalMethodDefinition(MethodDesc * pMethod, QCall::ObjectHandleOnStack refMethod)
2641     {            
2642     QCALL_CONTRACT;
2643
2644     BEGIN_QCALL;
2645 #ifdef _DEBUG
2646     {
2647         GCX_COOP();
2648         _ASSERTE(((ReflectMethodObject *)(*refMethod.m_ppObject))->GetMethod() == pMethod);
2649     }
2650 #endif
2651     MethodDesc *pMethodTypical = pMethod->LoadTypicalMethodDefinition();
2652     if (pMethodTypical != pMethod)
2653     {
2654         GCX_COOP();
2655         refMethod.Set(pMethodTypical->GetStubMethodInfo());
2656     }
2657     END_QCALL;
2658     
2659     return;
2660 }
2661
2662 void QCALLTYPE RuntimeMethodHandle::StripMethodInstantiation(MethodDesc * pMethod, QCall::ObjectHandleOnStack refMethod)
2663     {            
2664     QCALL_CONTRACT;
2665
2666     BEGIN_QCALL;
2667
2668     if (!pMethod)
2669         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
2670
2671 #ifdef _DEBUG
2672     {
2673         GCX_COOP();
2674         _ASSERTE(((ReflectMethodObject *)(*refMethod.m_ppObject))->GetMethod() == pMethod);
2675     }
2676 #endif
2677     MethodDesc *pMethodStripped = pMethod->StripMethodInstantiation();
2678     if (pMethodStripped != pMethod)
2679     {
2680         GCX_COOP();
2681         refMethod.Set(pMethodStripped->GetStubMethodInfo());
2682     }
2683     END_QCALL;
2684
2685     return;
2686 }
2687
2688 // In the VM there might be more than one MethodDescs for a "method"
2689 // examples are methods on generic types which may have additional instantiating stubs
2690 //          and methods on value types which may have additional unboxing stubs.
2691 //
2692 // For generic methods we always hand out an instantiating stub except for a generic method definition
2693 // For non-generic methods on generic types we need an instantiating stub if it's one of the following
2694 //  - static method on a generic class
2695 //  - static or instance method on a generic interface
2696 //  - static or instance method on a generic value type
2697 // The Reflection policy is to always hand out instantiating stubs in these cases
2698 //
2699 // For methods on non-generic value types we can use either the cannonical method or the unboxing stub
2700 // The Reflection policy is to always hand out unboxing stubs if the methods are virtual methods
2701 // The reason for this is that in the current implementation of the class loader, the v-table slots for 
2702 // those methods point to unboxing stubs already. Note that this is just a implementation choice
2703 // that might change in the future. But we should always keep this Reflection policy an invariant.
2704 // 
2705 // For virtual methods on generic value types (intersection of the two cases), reflection will hand
2706 // out an unboxing instantiating stub
2707 // 
2708 // GetInstantiatingStub is called to: 
2709 // 1. create an InstantiatedMethodDesc for a generic method when calling BindGenericArguments() on a generic
2710 //    method. In this case instArray will not be null.
2711 // 2. create an InstantiatedMethodDesc for a method in a generic class. In this case instArray will be null.
2712 // 3. create an UnboxingStub for a method in a value type. In this case instArray will be null.
2713 // For case 2 and 3, an instantiating stub or unboxing stub might not be needed in which case the original 
2714 // MethodDesc is returned.
2715 FCIMPL3(MethodDesc*, RuntimeMethodHandle::GetStubIfNeeded,
2716     MethodDesc *pMethod,
2717     ReflectClassBaseObject *pTypeUNSAFE,
2718     PtrArray* instArrayUNSAFE)
2719 {
2720     CONTRACTL {
2721         FCALL_CHECK;
2722     }
2723     CONTRACTL_END;
2724
2725     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2726     PTRARRAYREF instArray = (PTRARRAYREF)ObjectToOBJECTREF(instArrayUNSAFE);
2727
2728     if (refType == NULL)
2729         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2730
2731     TypeHandle instType = refType->GetType();
2732     MethodDesc *pNewMethod = pMethod;
2733
2734     // error conditions
2735     if (!pMethod)
2736         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
2737
2738     if (instType.IsNull())
2739         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2740     
2741     // Perf optimization: this logic is actually duplicated in FindOrCreateAssociatedMethodDescForReflection, but since it
2742     // is the more common case it's worth the duplicate check here to avoid the helper method frame
2743     if ( instArray == NULL &&
2744          ( pMethod->HasMethodInstantiation() || 
2745            ( !instType.IsValueType() && 
2746              ( !instType.HasInstantiation() || instType.IsGenericTypeDefinition() ) ) ) )
2747     {
2748         return pNewMethod;
2749     }
2750
2751     HELPER_METHOD_FRAME_BEGIN_RET_2(refType, instArray);
2752     {
2753         TypeHandle *inst = NULL;
2754         DWORD ntypars = 0;
2755
2756         if (instArray != NULL) 
2757         {
2758             ntypars = instArray->GetNumComponents();    
2759
2760             size_t size = ntypars * sizeof(TypeHandle);
2761             if ((size / sizeof(TypeHandle)) != ntypars) // uint over/underflow
2762                 COMPlusThrow(kArgumentException);
2763             inst = (TypeHandle*) _alloca(size);        
2764
2765             for (DWORD i = 0; i < ntypars; i++) 
2766             {
2767                 REFLECTCLASSBASEREF instRef = (REFLECTCLASSBASEREF)instArray->GetAt(i);
2768
2769                 if (instRef == NULL)
2770                     COMPlusThrowArgumentNull(W("inst"), W("ArgumentNull_ArrayElement"));
2771
2772                 inst[i] = instRef->GetType();
2773             }
2774         }
2775
2776         pNewMethod = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMethod, instType, Instantiation(inst, ntypars));
2777     }
2778     HELPER_METHOD_FRAME_END();
2779
2780     return pNewMethod;
2781 }
2782 FCIMPLEND
2783
2784         
2785 FCIMPL2(MethodDesc*, RuntimeMethodHandle::GetMethodFromCanonical, MethodDesc *pMethod, ReflectClassBaseObject *pTypeUNSAFE)
2786 {
2787     CONTRACTL {
2788         FCALL_CHECK;
2789         PRECONDITION(CheckPointer(pMethod));
2790     }
2791     CONTRACTL_END;
2792     
2793     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2794
2795     TypeHandle instType = refType->GetType();
2796     MethodDesc* pMDescInCanonMT = instType.GetMethodTable()->GetParallelMethodDesc(pMethod);
2797
2798     return pMDescInCanonMT;
2799 }
2800 FCIMPLEND
2801
2802
2803 FCIMPL2(MethodBody *, RuntimeMethodHandle::GetMethodBody, ReflectMethodObject *pMethodUNSAFE, ReflectClassBaseObject *pDeclaringTypeUNSAFE)
2804 {      
2805     CONTRACTL 
2806     {
2807         FCALL_CHECK;
2808     }
2809     CONTRACTL_END;
2810
2811     struct _gc
2812     {
2813         METHODBODYREF MethodBodyObj;
2814         EXCEPTIONHANDLINGCLAUSEREF EHClauseObj;
2815         LOCALVARIABLEINFOREF LocalVariableInfoObj;
2816         U1ARRAYREF                  U1Array;
2817         BASEARRAYREF                TempArray;
2818         REFLECTCLASSBASEREF         declaringType;
2819         REFLECTMETHODREF            refMethod;
2820     } gc;
2821
2822     gc.MethodBodyObj = NULL;
2823     gc.EHClauseObj = NULL;
2824     gc.LocalVariableInfoObj = NULL;
2825     gc.U1Array              = NULL;
2826     gc.TempArray            = NULL;
2827     gc.declaringType        = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
2828     gc.refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
2829
2830
2831     if (!gc.refMethod)
2832         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2833
2834     MethodDesc* pMethod = gc.refMethod->GetMethod();
2835
2836     TypeHandle declaringType = gc.declaringType == NULL ? TypeHandle() : gc.declaringType->GetType();
2837
2838     if (!pMethod->IsIL())
2839         return NULL;
2840
2841     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
2842     {
2843         MethodDesc *pMethodIL = pMethod;
2844         if (pMethod->IsWrapperStub())
2845             pMethodIL = pMethod->GetWrappedMethodDesc();
2846         
2847         COR_ILMETHOD* pILHeader = pMethodIL->GetILHeader();
2848         
2849         if (pILHeader)
2850         {
2851             MethodTable * pExceptionHandlingClauseMT = MscorlibBinder::GetClass(CLASS__EH_CLAUSE);
2852             TypeHandle thEHClauseArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pExceptionHandlingClauseMT), ELEMENT_TYPE_SZARRAY);
2853
2854             MethodTable * pLocalVariableMT = MscorlibBinder::GetClass(CLASS__LOCAL_VARIABLE_INFO);
2855             TypeHandle thLocalVariableArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pLocalVariableMT), ELEMENT_TYPE_SZARRAY);
2856
2857             Module* pModule = pMethod->GetModule();
2858             COR_ILMETHOD_DECODER::DecoderStatus status;
2859             COR_ILMETHOD_DECODER header(pILHeader, pModule->GetMDImport(), &status);
2860
2861             if (status != COR_ILMETHOD_DECODER::SUCCESS)
2862             {
2863                 if (status == COR_ILMETHOD_DECODER::VERIFICATION_ERROR)
2864                 {
2865                     // Throw a verification HR
2866                     COMPlusThrowHR(COR_E_VERIFICATION);
2867                 }
2868                 else
2869                 {
2870                     COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
2871                 }
2872             }
2873
2874             gc.MethodBodyObj = (METHODBODYREF)AllocateObject(MscorlibBinder::GetClass(CLASS__METHOD_BODY));
2875             
2876             gc.MethodBodyObj->m_maxStackSize = header.GetMaxStack();
2877             gc.MethodBodyObj->m_initLocals = !!(header.GetFlags() & CorILMethod_InitLocals);
2878
2879             if (header.IsFat())
2880                 gc.MethodBodyObj->m_localVarSigToken = header.GetLocalVarSigTok();
2881             else
2882                 gc.MethodBodyObj->m_localVarSigToken = 0;
2883
2884             // Allocate the array of IL and fill it in from the method header.
2885             BYTE* pIL = const_cast<BYTE*>(header.Code);
2886             COUNT_T cIL = header.GetCodeSize();
2887             gc.U1Array  = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, cIL);
2888
2889             SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_IL, gc.U1Array, GetAppDomain());
2890             memcpyNoGCRefs(gc.MethodBodyObj->m_IL->GetDataPtr(), pIL, cIL);
2891
2892             // Allocate the array of exception clauses.
2893             INT32 cEh = (INT32)header.EHCount();
2894             const COR_ILMETHOD_SECT_EH* ehInfo = header.EH;
2895             gc.TempArray = (BASEARRAYREF) AllocateArrayEx(thEHClauseArray, &cEh, 1);
2896
2897             SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_exceptionClauses, gc.TempArray, GetAppDomain());
2898             
2899             for (INT32 i = 0; i < cEh; i++)
2900             {                    
2901                 COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff; 
2902                 const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehClause = 
2903                     (const COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)ehInfo->EHClause(i, &ehBuff); 
2904
2905                 gc.EHClauseObj = (EXCEPTIONHANDLINGCLAUSEREF) AllocateObject(pExceptionHandlingClauseMT);
2906
2907                 gc.EHClauseObj->m_flags = ehClause->GetFlags();  
2908                 gc.EHClauseObj->m_tryOffset = ehClause->GetTryOffset();
2909                 gc.EHClauseObj->m_tryLength = ehClause->GetTryLength();
2910                 gc.EHClauseObj->m_handlerOffset = ehClause->GetHandlerOffset();
2911                 gc.EHClauseObj->m_handlerLength = ehClause->GetHandlerLength();
2912                 
2913                 if ((ehClause->GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER) == 0)
2914                     gc.EHClauseObj->m_catchToken = ehClause->GetClassToken();
2915                 else
2916                     gc.EHClauseObj->m_filterOffset = ehClause->GetFilterOffset();
2917                 
2918                 gc.MethodBodyObj->m_exceptionClauses->SetAt(i, (OBJECTREF) gc.EHClauseObj);
2919                 SetObjectReference((OBJECTREF*)&(gc.EHClauseObj->m_methodBody), (OBJECTREF)gc.MethodBodyObj, GetAppDomain());
2920             }     
2921            
2922             if (header.LocalVarSig != NULL)
2923             {
2924                 SigTypeContext sigTypeContext(pMethod, declaringType, pMethod->LoadMethodInstantiation());
2925                 MetaSig metaSig(header.LocalVarSig, 
2926                                 header.cbLocalVarSig, 
2927                                 pModule, 
2928                                 &sigTypeContext, 
2929                                 MetaSig::sigLocalVars);
2930                 INT32 cLocals = metaSig.NumFixedArgs();
2931                 gc.TempArray  = (BASEARRAYREF) AllocateArrayEx(thLocalVariableArray, &cLocals, 1);
2932                 SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_localVariables, gc.TempArray, GetAppDomain());
2933
2934                 for (INT32 i = 0; i < cLocals; i ++)
2935                 {
2936                     gc.LocalVariableInfoObj = (LOCALVARIABLEINFOREF)AllocateObject(pLocalVariableMT);
2937
2938                     gc.LocalVariableInfoObj->m_localIndex = i;
2939                     
2940                     metaSig.NextArg();
2941
2942                     CorElementType eType;
2943                     IfFailThrow(metaSig.GetArgProps().PeekElemType(&eType));
2944                     if (ELEMENT_TYPE_PINNED == eType)
2945                         gc.LocalVariableInfoObj->m_bIsPinned = TRUE;
2946
2947                     TypeHandle  tempType= metaSig.GetArgProps().GetTypeHandleThrowing(pModule, &sigTypeContext);       
2948                     OBJECTREF refLocalType = tempType.GetManagedClassObject();
2949                     gc.LocalVariableInfoObj->SetType(refLocalType);
2950                     gc.MethodBodyObj->m_localVariables->SetAt(i, (OBJECTREF) gc.LocalVariableInfoObj);
2951                 }        
2952             }
2953             else
2954             {
2955                 INT32 cLocals = 0;
2956                 gc.TempArray  = (BASEARRAYREF) AllocateArrayEx(thLocalVariableArray, &cLocals, 1);
2957                 SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_localVariables, gc.TempArray, GetAppDomain());
2958             }
2959         }
2960     }
2961     HELPER_METHOD_FRAME_END();
2962
2963     return (MethodBody*)OBJECTREFToObject(gc.MethodBodyObj);
2964 }
2965 FCIMPLEND
2966
2967 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsConstructor, MethodDesc *pMethod)
2968 {
2969     CONTRACTL {
2970         FCALL_CHECK;
2971         PRECONDITION(CheckPointer(pMethod));
2972     }
2973     CONTRACTL_END;
2974
2975     BOOL ret = FALSE;
2976     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
2977     ret = (BOOL)pMethod->IsClassConstructorOrCtor();
2978     END_SO_INTOLERANT_CODE;
2979     FC_RETURN_BOOL(ret);
2980 }
2981 FCIMPLEND
2982
2983 FCIMPL1(Object*, RuntimeMethodHandle::GetLoaderAllocator, MethodDesc *pMethod)
2984 {
2985     CONTRACTL {
2986         FCALL_CHECK;
2987     }
2988     CONTRACTL_END;
2989
2990     OBJECTREF loaderAllocator = NULL;
2991
2992     if (!pMethod)
2993         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2994
2995     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(loaderAllocator);
2996
2997     LoaderAllocator *pLoaderAllocator = pMethod->GetLoaderAllocator();
2998     loaderAllocator = pLoaderAllocator->GetExposedObject();
2999
3000     HELPER_METHOD_FRAME_END();
3001
3002     return OBJECTREFToObject(loaderAllocator);
3003 }
3004 FCIMPLEND
3005
3006 //*********************************************************************************************
3007 //*********************************************************************************************
3008 //*********************************************************************************************
3009
3010 FCIMPL1(StringObject*, RuntimeFieldHandle::GetName, ReflectFieldObject *pFieldUNSAFE) {
3011     CONTRACTL {
3012         FCALL_CHECK;
3013     }
3014     CONTRACTL_END;
3015     
3016     REFLECTFIELDREF refField = (REFLECTFIELDREF)ObjectToOBJECTREF(pFieldUNSAFE);
3017     if (!refField)
3018         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3019         
3020     FieldDesc *pField = refField->GetField();
3021     
3022     STRINGREF refString = NULL;
3023     HELPER_METHOD_FRAME_BEGIN_RET_1(refField);
3024     {
3025         refString = StringObject::NewString(pField->GetName());
3026     }
3027     HELPER_METHOD_FRAME_END();
3028     return (StringObject*)OBJECTREFToObject(refString);
3029 }
3030 FCIMPLEND
3031     
3032 FCIMPL1(LPCUTF8, RuntimeFieldHandle::GetUtf8Name, FieldDesc *pField) {
3033     CONTRACTL {
3034         FCALL_CHECK;
3035         PRECONDITION(CheckPointer(pField));
3036     }
3037     CONTRACTL_END;
3038     
3039     LPCUTF8    szFieldName;
3040     
3041     if (FAILED(pField->GetName_NoThrow(&szFieldName)))
3042     {
3043         FCThrow(kBadImageFormatException);
3044     }
3045     return szFieldName;
3046 }
3047 FCIMPLEND
3048
3049 FCIMPL2(FC_BOOL_RET, RuntimeFieldHandle::MatchesNameHash, FieldDesc * pField, ULONG hash)
3050 {
3051     FCALL_CONTRACT;
3052
3053     FC_RETURN_BOOL(pField->MightHaveName(hash));
3054 }
3055 FCIMPLEND
3056
3057 FCIMPL1(INT32, RuntimeFieldHandle::GetAttributes, FieldDesc *pField) {
3058     CONTRACTL {
3059         FCALL_CHECK;
3060     }
3061     CONTRACTL_END;
3062     
3063     if (!pField)
3064         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3065
3066     INT32 ret = 0;
3067     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
3068     ret = (INT32)pField->GetAttributes();
3069     END_SO_INTOLERANT_CODE;
3070     return ret;
3071 }
3072 FCIMPLEND
3073     
3074 FCIMPL1(ReflectClassBaseObject*, RuntimeFieldHandle::GetApproxDeclaringType, FieldDesc *pField) {
3075     CONTRACTL {
3076         FCALL_CHECK;
3077     }
3078     CONTRACTL_END;
3079     
3080     if (!pField)
3081         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3082         
3083     TypeHandle th = TypeHandle(pField->GetApproxEnclosingMethodTable());  // <REVISIT_TODO> this needs to be checked - see bug 184355 </REVISIT_TODO>
3084     RETURN_CLASS_OBJECT(th, NULL);
3085 }
3086 FCIMPLEND
3087
3088 FCIMPL1(INT32, RuntimeFieldHandle::GetToken, ReflectFieldObject *pFieldUNSAFE) {
3089     CONTRACTL {
3090         FCALL_CHECK;
3091     }
3092     CONTRACTL_END;
3093
3094     REFLECTFIELDREF refField = (REFLECTFIELDREF)ObjectToOBJECTREF(pFieldUNSAFE);
3095     if (!refField)
3096         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3097         
3098     FieldDesc *pField = refField->GetField();
3099
3100     INT32 tkFieldDef = (INT32)pField->GetMemberDef();
3101     _ASSERTE(!IsNilToken(tkFieldDef) || tkFieldDef == mdFieldDefNil);
3102     return tkFieldDef;
3103 }
3104 FCIMPLEND
3105
3106 FCIMPL2(FieldDesc*, RuntimeFieldHandle::GetStaticFieldForGenericType, FieldDesc *pField, ReflectClassBaseObject *pDeclaringTypeUNSAFE)
3107 {
3108     CONTRACTL {
3109         FCALL_CHECK;
3110     }
3111     CONTRACTL_END;
3112
3113     REFLECTCLASSBASEREF refDeclaringType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
3114
3115     if ((refDeclaringType == NULL) || (pField == NULL))
3116         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3117
3118     TypeHandle declaringType = refDeclaringType->GetType();
3119     
3120     if (!pField)
3121         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3122     if (declaringType.IsTypeDesc())
3123         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3124     MethodTable *pMT = declaringType.AsMethodTable();
3125
3126     _ASSERTE(pField->IsStatic());
3127     if (pMT->HasGenericsStaticsInfo())
3128         pField = pMT->GetFieldDescByIndex(pField->GetApproxEnclosingMethodTable()->GetIndexForFieldDesc(pField));
3129     _ASSERTE(!pField->IsSharedByGenericInstantiations());
3130     _ASSERTE(pField->GetEnclosingMethodTable() == pMT);
3131
3132     return pField;
3133 }
3134 FCIMPLEND
3135
3136 FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBaseObject* pAssemblyUNSAFE) {
3137     FCALL_CONTRACT;
3138
3139     ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
3140     
3141     if (refAssembly == NULL)
3142         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3143
3144     DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
3145     Assembly* currentAssembly = pAssembly->GetCurrentAssembly();
3146
3147     if (currentAssembly == NULL)
3148         return NULL;
3149
3150     Module *pModule = currentAssembly->GetManifestModule();
3151     DomainFile * pDomainFile = pModule->FindDomainFile(GetAppDomain());
3152
3153 #ifdef _DEBUG
3154     OBJECTREF orModule;
3155     
3156     HELPER_METHOD_FRAME_BEGIN_RET_1(refAssembly);
3157     orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
3158     if (orModule == NULL)
3159         orModule = pModule->GetExposedObject();
3160 #else
3161     OBJECTREF orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
3162     if (orModule != NULL)
3163         return (ReflectModuleBaseObject*)OBJECTREFToObject(orModule);
3164
3165     HELPER_METHOD_FRAME_BEGIN_RET_1(refAssembly);
3166     orModule = pModule->GetExposedObject();
3167 #endif
3168
3169     HELPER_METHOD_FRAME_END();
3170     return (ReflectModuleBaseObject*)OBJECTREFToObject(orModule);
3171
3172 }
3173 FCIMPLEND
3174
3175 FCIMPL1(INT32, AssemblyHandle::GetToken, AssemblyBaseObject* pAssemblyUNSAFE) {
3176     FCALL_CONTRACT;
3177     
3178     ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
3179     
3180     if (refAssembly == NULL)
3181         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3182
3183     DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
3184     mdAssembly token = mdAssemblyNil;
3185     
3186     IMDInternalImport *mdImport = pAssembly->GetCurrentAssembly()->GetManifestImport();
3187     
3188     if (mdImport != 0)
3189     {
3190         if (FAILED(mdImport->GetAssemblyFromScope(&token)))
3191         {
3192             FCThrow(kBadImageFormatException);
3193         }
3194     }
3195     
3196     return token;
3197 }
3198 FCIMPLEND
3199
3200     
3201 void QCALLTYPE ModuleHandle::GetPEKind(QCall::ModuleHandle pModule, DWORD* pdwPEKind, DWORD* pdwMachine)
3202 {
3203     QCALL_CONTRACT;
3204
3205     BEGIN_QCALL;
3206     pModule->GetFile()->GetPEKindAndMachine(pdwPEKind, pdwMachine);
3207     END_QCALL;
3208 }
3209
3210 FCIMPL1(INT32, ModuleHandle::GetMDStreamVersion, ReflectModuleBaseObject * pModuleUNSAFE)
3211 {
3212     FCALL_CONTRACT;
3213
3214     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
3215
3216     if (refModule == NULL)
3217         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3218
3219     Module *pModule = refModule->GetModule();
3220     
3221     if (pModule->IsResource())
3222         return 0;
3223     
3224     return pModule->GetMDImport()->GetMetadataStreamVersion();   
3225 }
3226 FCIMPLEND
3227
3228 void QCALLTYPE ModuleHandle::GetModuleType(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retType)
3229 {
3230     QCALL_CONTRACT;
3231
3232     TypeHandle globalTypeHandle = TypeHandle();
3233     
3234     BEGIN_QCALL;
3235     
3236         EX_TRY
3237         {          
3238             globalTypeHandle = TypeHandle(pModule->GetGlobalMethodTable());
3239         }
3240         EX_SWALLOW_NONTRANSIENT;
3241
3242         if (!globalTypeHandle.IsNull())
3243         {
3244             GCX_COOP();
3245             retType.Set(globalTypeHandle.GetManagedClassObject());
3246         }
3247
3248     END_QCALL;
3249
3250     return;
3251 }
3252
3253 FCIMPL1(INT32, ModuleHandle::GetToken, ReflectModuleBaseObject * pModuleUNSAFE) {
3254     CONTRACTL {
3255         FCALL_CHECK;
3256     }
3257     CONTRACTL_END;
3258
3259     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
3260
3261     if (refModule == NULL)
3262         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3263
3264     Module *pModule = refModule->GetModule();
3265     
3266     if (pModule->IsResource())
3267         return mdModuleNil;
3268     
3269     return pModule->GetMDImport()->GetModuleFromScope();
3270 }
3271 FCIMPLEND
3272
3273 FCIMPL1(IMDInternalImport*, ModuleHandle::GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE)
3274 {
3275     FCALL_CONTRACT;
3276
3277     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
3278
3279     if (refModule == NULL)
3280         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3281
3282     Module *pModule = refModule->GetModule();
3283
3284     if (pModule->IsResource())
3285         return NULL;
3286
3287     return pModule->GetMDImport();
3288 }
3289 FCIMPLEND
3290
3291 BOOL QCALLTYPE ModuleHandle::ContainsPropertyMatchingHash(QCall::ModuleHandle pModule, INT32 tkProperty, ULONG hash)
3292 {
3293     QCALL_CONTRACT;
3294
3295     BOOL fContains = TRUE;
3296
3297     BEGIN_QCALL;
3298
3299     fContains = pModule->MightContainMatchingProperty(tkProperty, hash);
3300
3301     END_QCALL;
3302
3303     return fContains;
3304 }
3305
3306 void QCALLTYPE ModuleHandle::ResolveType(QCall::ModuleHandle pModule, INT32 tkType, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount, QCall::ObjectHandleOnStack retType)
3307 {
3308     QCALL_CONTRACT;
3309
3310     TypeHandle typeHandle;
3311     
3312     BEGIN_QCALL;
3313     
3314     _ASSERTE(!IsNilToken(tkType));
3315
3316     SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
3317         typeHandle = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, tkType, &typeContext, 
3318                                                           ClassLoader::ThrowIfNotFound, 
3319                                                           ClassLoader::PermitUninstDefOrRef);
3320
3321     GCX_COOP();
3322     retType.Set(typeHandle.GetManagedClassObject());
3323
3324     END_QCALL;
3325
3326     return;
3327 }
3328
3329 MethodDesc *QCALLTYPE ModuleHandle::ResolveMethod(QCall::ModuleHandle pModule, INT32 tkMemberRef, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount)
3330 {
3331     QCALL_CONTRACT;
3332
3333     MethodDesc* pMD = NULL;
3334     
3335     BEGIN_QCALL;
3336
3337     _ASSERTE(!IsNilToken(tkMemberRef));
3338
3339     BOOL strictMetadataChecks = (TypeFromToken(tkMemberRef) == mdtMethodSpec);
3340
3341     SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
3342     pMD = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(pModule, tkMemberRef, &typeContext, strictMetadataChecks, FALSE);
3343
3344     // This will get us the instantiating or unboxing stub if needed
3345     pMD = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMD, pMD->GetMethodTable(), pMD->GetMethodInstantiation());
3346
3347     END_QCALL;
3348
3349     return pMD;
3350 }
3351
3352 void QCALLTYPE ModuleHandle::ResolveField(QCall::ModuleHandle pModule, INT32 tkMemberRef, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount, QCall::ObjectHandleOnStack retField)
3353 {
3354     QCALL_CONTRACT;
3355
3356     FieldDesc* pField = NULL;
3357     
3358     BEGIN_QCALL;
3359
3360     _ASSERTE(!IsNilToken(tkMemberRef));
3361
3362     SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
3363     pField = MemberLoader::GetFieldDescFromMemberDefOrRef(pModule, tkMemberRef, &typeContext, FALSE);
3364     GCX_COOP();
3365     retField.Set(pField->GetStubFieldInfo());
3366
3367     END_QCALL;
3368
3369     return;
3370 }
3371
3372 void QCALLTYPE ModuleHandle::GetAssembly(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retAssembly)
3373 {
3374     QCALL_CONTRACT;
3375
3376     DomainAssembly *pAssembly = NULL;
3377
3378     BEGIN_QCALL;
3379     pAssembly = pModule->GetDomainAssembly();
3380
3381     GCX_COOP();
3382     retAssembly.Set(pAssembly->GetExposedAssemblyObject());
3383     END_QCALL;
3384
3385     return;
3386 }
3387
3388 FCIMPL5(ReflectMethodObject*, ModuleHandle::GetDynamicMethod, ReflectMethodObject *pMethodUNSAFE, ReflectModuleBaseObject *pModuleUNSAFE, StringObject *name, U1Array *sig,  Object *resolver) {
3389     CONTRACTL {
3390         FCALL_CHECK;
3391         PRECONDITION(CheckPointer(name));
3392         PRECONDITION(CheckPointer(sig));
3393     }
3394     CONTRACTL_END;
3395     
3396     DynamicMethodDesc *pNewMD = NULL;
3397
3398     struct
3399     {
3400         STRINGREF nameRef;
3401         OBJECTREF resolverRef;
3402         OBJECTREF methodRef;
3403         REFLECTMETHODREF retMethod;
3404         REFLECTMODULEBASEREF refModule;
3405     } gc;
3406     gc.nameRef = (STRINGREF)name;
3407     gc.resolverRef = (OBJECTREF)resolver;
3408     gc.methodRef = ObjectToOBJECTREF(pMethodUNSAFE);
3409     gc.retMethod = NULL;
3410     gc.refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
3411
3412     if (gc.refModule == NULL)
3413         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3414
3415     Module *pModule = gc.refModule->GetModule();
3416
3417     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
3418     
3419     DomainFile *pDomainModule = pModule->GetDomainFile();
3420
3421     U1ARRAYREF dataArray = (U1ARRAYREF)sig;
3422     DWORD sigSize = dataArray->GetNumComponents();
3423     NewHolder<BYTE> pSig(new BYTE[sigSize]);
3424     memcpy(pSig, dataArray->GetDataPtr(), sigSize);
3425
3426     DWORD length = gc.nameRef->GetStringLength();
3427     NewArrayHolder<char> pName(new char[(length + 1) * 2]);
3428     pName[0] = '\0';
3429     length = WszWideCharToMultiByte(CP_UTF8, 0, gc.nameRef->GetBuffer(), length, pName, (length + 1) * 2 - sizeof(char), NULL, NULL);
3430     if (length)
3431         pName[length / sizeof(char)] = '\0';
3432
3433     DynamicMethodTable *pMTForDynamicMethods = pDomainModule->GetDynamicMethodTable();
3434     pNewMD = pMTForDynamicMethods->GetDynamicMethod(pSig, sigSize, pName);
3435     _ASSERTE(pNewMD != NULL);
3436     // pNewMD now owns pSig and pName.
3437     pSig.SuppressRelease();
3438     pName.SuppressRelease();
3439
3440     // create a handle to hold the resolver objectref
3441     OBJECTHANDLE resolverHandle = pDomainModule->GetAppDomain()->CreateLongWeakHandle(gc.resolverRef);
3442     pNewMD->GetLCGMethodResolver()->SetManagedResolver(resolverHandle);
3443     gc.retMethod = pNewMD->GetStubMethodInfo();
3444     gc.retMethod->SetKeepAlive(gc.resolverRef);
3445
3446     LoaderAllocator *pLoaderAllocator = pModule->GetLoaderAllocator();
3447
3448     if (pLoaderAllocator->IsCollectible())
3449         pLoaderAllocator->AddReference();
3450    
3451     HELPER_METHOD_FRAME_END();
3452
3453     return (ReflectMethodObject*)OBJECTREFToObject(gc.retMethod);
3454 }
3455 FCIMPLEND
3456
3457 void QCALLTYPE RuntimeMethodHandle::GetCallerType(QCall::StackCrawlMarkHandle pStackMark, QCall::ObjectHandleOnStack retType)
3458
3459     QCALL_CONTRACT;
3460
3461     BEGIN_QCALL;
3462     GCX_COOP();
3463     MethodTable *pMT = NULL;
3464
3465     pMT = SystemDomain::GetCallersType(pStackMark);
3466
3467     if (pMT != NULL)
3468         retType.Set(pMT->GetManagedClassObject());
3469
3470     END_QCALL;
3471
3472     return;
3473 }