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