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