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