summaryrefslogtreecommitdiff
path: root/src/vm/runtimehandles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/runtimehandles.cpp')
-rw-r--r--src/vm/runtimehandles.cpp3569
1 files changed, 3569 insertions, 0 deletions
diff --git a/src/vm/runtimehandles.cpp b/src/vm/runtimehandles.cpp
new file mode 100644
index 0000000000..68ad24c8f6
--- /dev/null
+++ b/src/vm/runtimehandles.cpp
@@ -0,0 +1,3569 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+#include "common.h"
+#include "corhdr.h"
+#include "runtimehandles.h"
+#include "object.h"
+#include "class.h"
+#include "method.hpp"
+#include "typehandle.h"
+#include "field.h"
+#include "siginfo.hpp"
+#include "clsload.hpp"
+#include "typestring.h"
+#include "typeparse.h"
+#include "holder.h"
+#include "codeman.h"
+#include "corhlpr.h"
+#include "jitinterface.h"
+#include "stackprobe.h"
+#include "eeconfig.h"
+#include "eehash.h"
+#include "objecthandle.h"
+#include "interoputil.h"
+#include "typedesc.h"
+#include "virtualcallstub.h"
+#include "contractimpl.h"
+#include "dynamicmethod.h"
+#include "peimagelayout.inl"
+#include "security.h"
+#include "eventtrace.h"
+#include "invokeutil.h"
+
+
+FCIMPL3(FC_BOOL_RET, Utf8String::EqualsCaseSensitive, LPCUTF8 szLhs, LPCUTF8 szRhs, INT32 stringNumBytes)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(szLhs));
+ PRECONDITION(CheckPointer(szRhs));
+ }
+ CONTRACTL_END;
+
+ // Important: the string in pSsz isn't null terminated so the length must be used
+ // when performing operations on the string.
+
+ // At this point, both the left and right strings are guaranteed to have the
+ // same length.
+ FC_RETURN_BOOL(strncmp(szLhs, szRhs, stringNumBytes) == 0);
+}
+FCIMPLEND
+
+BOOL QCALLTYPE Utf8String::EqualsCaseInsensitive(LPCUTF8 szLhs, LPCUTF8 szRhs, INT32 stringNumBytes)
+{
+ QCALL_CONTRACT;
+
+ // Important: the string in pSsz isn't null terminated so the length must be used
+ // when performing operations on the string.
+
+ BOOL fStringsEqual = FALSE;
+
+ BEGIN_QCALL;
+
+ _ASSERTE(CheckPointer(szLhs));
+ _ASSERTE(CheckPointer(szRhs));
+
+ // At this point, both the left and right strings are guaranteed to have the
+ // same length.
+ StackSString lhs(SString::Utf8, szLhs, stringNumBytes);
+ StackSString rhs(SString::Utf8, szRhs, stringNumBytes);
+
+ // We can use SString for simple case insensitive compares
+ fStringsEqual = lhs.EqualsCaseInsensitive(rhs);
+
+ END_QCALL;
+
+ return fStringsEqual;
+}
+
+ULONG QCALLTYPE Utf8String::HashCaseInsensitive(LPCUTF8 sz, INT32 stringNumBytes)
+{
+ QCALL_CONTRACT;
+
+ // Important: the string in pSsz isn't null terminated so the length must be used
+ // when performing operations on the string.
+
+ ULONG hashValue = 0;
+
+ BEGIN_QCALL;
+
+ StackSString str(SString::Utf8, sz, stringNumBytes);
+ hashValue = str.HashCaseInsensitive();
+
+ END_QCALL;
+
+ return hashValue;
+}
+
+static BOOL CheckCAVisibilityFromDecoratedType(MethodTable* pCAMT, MethodDesc* pCACtor, MethodTable* pDecoratedMT, Module* pDecoratedModule)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pCAMT));
+ PRECONDITION(CheckPointer(pCACtor, NULL_OK));
+ PRECONDITION(CheckPointer(pDecoratedMT, NULL_OK));
+ PRECONDITION(CheckPointer(pDecoratedModule));
+ }
+ CONTRACTL_END;
+
+ DWORD dwAttr = mdPublic;
+
+ if (pCACtor != NULL)
+ {
+ // Allowing a dangerous method to be called in custom attribute instantiation is, well, dangerous.
+ // E.g. a malicious user can craft a custom attribute record that fools us into creating a DynamicMethod
+ // object attached to typeof(System.Reflection.CustomAttribute) and thus gain access to mscorlib internals.
+ if (InvokeUtil::IsDangerousMethod(pCACtor))
+ return FALSE;
+
+ _ASSERTE(pCACtor->IsCtor());
+
+ dwAttr = pCACtor->GetAttrs();
+ }
+
+ StaticAccessCheckContext accessContext(NULL, pDecoratedMT, pDecoratedModule->GetAssembly());
+
+ // Don't do transparency check here. Custom attributes have different transparency rules.
+ // The checks are done by AllowCriticalCustomAttributes and CheckLinktimeDemands in CustomAttribute.cs.
+ return ClassLoader::CanAccess(
+ &accessContext,
+ pCAMT,
+ pCAMT->GetAssembly(),
+ dwAttr,
+ pCACtor,
+ NULL,
+ *AccessCheckOptions::s_pNormalAccessChecks,
+ FALSE,
+ FALSE);
+}
+
+BOOL QCALLTYPE RuntimeMethodHandle::IsCAVisibleFromDecoratedType(
+ EnregisteredTypeHandle targetTypeHandle,
+ MethodDesc * pTargetCtor,
+ EnregisteredTypeHandle sourceTypeHandle,
+ QCall::ModuleHandle sourceModuleHandle)
+{
+ QCALL_CONTRACT;
+
+ BOOL bResult = TRUE;
+
+ BEGIN_QCALL;
+ TypeHandle sourceHandle = TypeHandle::FromPtr(sourceTypeHandle);
+ TypeHandle targetHandle = TypeHandle::FromPtr(targetTypeHandle);
+
+ _ASSERTE((sourceHandle.IsNull() || !sourceHandle.IsTypeDesc()) &&
+ !targetHandle.IsNull() &&
+ !targetHandle.IsTypeDesc());
+
+ if (sourceHandle.IsTypeDesc() ||
+ targetHandle.IsNull() ||
+ targetHandle.IsTypeDesc())
+ COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
+
+ bResult = CheckCAVisibilityFromDecoratedType(targetHandle.AsMethodTable(), pTargetCtor, sourceHandle.AsMethodTable(), sourceModuleHandle);
+ END_QCALL;
+
+ return bResult;
+}
+
+// static
+BOOL QCALLTYPE RuntimeMethodHandle::IsSecurityCritical(MethodDesc *pMD)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pMD));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsCritical = TRUE;
+
+ BEGIN_QCALL;
+
+ if (pMD == NULL)
+ COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
+
+ fIsCritical = Security::IsMethodCritical(pMD);
+
+ END_QCALL;
+
+ return fIsCritical;
+}
+
+// static
+BOOL QCALLTYPE RuntimeMethodHandle::IsSecuritySafeCritical(MethodDesc *pMD)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pMD));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsSafeCritical = TRUE;
+
+ BEGIN_QCALL;
+
+ if (pMD == NULL)
+ COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
+
+ fIsSafeCritical = Security::IsMethodSafeCritical(pMD);
+
+ END_QCALL;
+
+ return fIsSafeCritical;
+}
+
+// static
+BOOL QCALLTYPE RuntimeMethodHandle::IsSecurityTransparent(MethodDesc *pMD)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pMD));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsTransparent = TRUE;
+
+ BEGIN_QCALL;
+
+ if (pMD == NULL)
+ COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
+
+ fIsTransparent = Security::IsMethodTransparent(pMD);
+
+ END_QCALL;
+
+ return fIsTransparent;
+}
+
+FCIMPL2(FC_BOOL_RET, RuntimeMethodHandle::IsTokenSecurityTransparent, ReflectModuleBaseObject *pModuleUNSAFE, INT32 tkToken) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
+
+ if(refModule == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ Module *pModule = refModule->GetModule();
+
+ BOOL bIsSecurityTransparent = TRUE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refModule);
+ {
+ bIsSecurityTransparent = Security::IsTokenTransparent(pModule, tkToken);
+ }
+ HELPER_METHOD_FRAME_END();
+
+ FC_RETURN_BOOL(bIsSecurityTransparent );
+
+}
+FCIMPLEND
+
+static bool DoAttributeTransparencyChecks(Assembly *pAttributeAssembly, Assembly *pDecoratedAssembly)
+{
+ CONTRACTL
+ {
+ THROWS;
+ MODE_COOPERATIVE;
+ GC_TRIGGERS;
+ PRECONDITION(CheckPointer(pAttributeAssembly));
+ PRECONDITION(CheckPointer(pDecoratedAssembly));
+ }
+ CONTRACTL_END;
+
+ // Do transparency checks - if both the decorated assembly and attribute use the v4 security model,
+ // then we can do a direct transparency check. However, if the decorated assembly uses the v2
+ // security model, then we need to convert the security critical attribute to looking as though it
+ // has a LinkDemand for full trust.
+ const SecurityTransparencyBehavior *pTargetTransparency = pDecoratedAssembly->GetSecurityTransparencyBehavior();
+ const SecurityTransparencyBehavior *pAttributeTransparency = pAttributeAssembly->GetSecurityTransparencyBehavior();
+
+ // v2 transparency did not impose checks for using its custom attributes, so if the attribute is
+ // defined in an assembly using the v2 transparency model then we don't need to do any
+ // additional checks.
+ if (pAttributeTransparency->DoAttributesRequireTransparencyChecks())
+ {
+ if (pTargetTransparency->CanTransparentCodeCallLinkDemandMethods() &&
+ pAttributeTransparency->CanCriticalMembersBeConvertedToLinkDemand())
+ {
+ // We have a v4 critical attribute being applied to a v2 transparent target. Since v2
+ // transparency doesn't understand externally visible critical attributes, we convert the
+ // attribute to a LinkDemand for full trust. v2 transparency did not convert
+ // LinkDemands on its attributes into full demands so we do not do that second level of
+ // conversion here either.
+ Security::FullTrustLinkDemand(pDecoratedAssembly);
+ return true;
+ }
+ else
+ {
+ // If we are here either the target of the attribute uses the v4 security model, or the
+ // attribute itself uses the v2 model. In these cases, we cannot perform a conversion of
+ // the critical attribute into a LinkDemand, and we have an error condition.
+ return false;
+ }
+ }
+
+ return true;
+}
+
+FCIMPL3(void, RuntimeMethodHandle::CheckLinktimeDemands, ReflectMethodObject *pMethodUNSAFE, ReflectModuleBaseObject *pModuleUNSAFE, CLR_BOOL isDecoratedTargetSecurityTransparent)
+{
+ CONTRACTL
+ {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(pModuleUNSAFE));
+ PRECONDITION(CheckPointer(pMethodUNSAFE));
+ }
+ CONTRACTL_END;
+
+ if(!Security::IsTransparencyEnforcementEnabled())
+ {
+ FCUnique(0xb0);
+ return;
+ }
+
+ REFLECTMETHODREF refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
+ REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
+
+ HELPER_METHOD_FRAME_BEGIN_2(refMethod, refModule);
+ {
+ MethodDesc *pCallee = refMethod->GetMethod(); // pCallee is the CA ctor or CA setter method
+ Module *pDecoratedModule = refModule->GetModule();
+
+ bool isAttributeSecurityCritical = Security::IsMethodCritical(pCallee) &&
+ !Security::IsMethodSafeCritical(pCallee);
+
+ if (isDecoratedTargetSecurityTransparent && isAttributeSecurityCritical)
+ {
+ if (!DoAttributeTransparencyChecks(pCallee->GetAssembly(), pDecoratedModule->GetAssembly()))
+ {
+ SecurityTransparent::ThrowMethodAccessException(pCallee);
+ }
+ }
+
+#ifndef FEATURE_CORECLR
+ if (pCallee->RequiresLinktimeCheck())
+ {
+ Module *pModule = refModule->GetModule();
+ Security::LinktimeCheckMethod(pDecoratedModule->GetAssembly(), pCallee);
+ }
+#endif // !FEATURE_CORECLR
+ }
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+NOINLINE static ReflectClassBaseObject* GetRuntimeTypeHelper(LPVOID __me, TypeHandle typeHandle, OBJECTREF keepAlive)
+{
+ FC_INNER_PROLOG_NO_ME_SETUP();
+ if (typeHandle.AsPtr() == NULL)
+ return NULL;
+
+ // RuntimeTypeHandle::GetRuntimeType has picked off the most common case, but does not cover array types.
+ // Before we do the really heavy weight option of setting up a helper method frame, check if we have to.
+ OBJECTREF refType = typeHandle.GetManagedClassObjectFast();
+ if (refType != NULL)
+ return (ReflectClassBaseObject*)OBJECTREFToObject(refType);
+
+ HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
+ refType = typeHandle.GetManagedClassObject();
+ HELPER_METHOD_FRAME_END();
+
+ FC_INNER_EPILOG();
+ return (ReflectClassBaseObject*)OBJECTREFToObject(refType);
+}
+
+#define RETURN_CLASS_OBJECT(typeHandle, keepAlive) FC_INNER_RETURN(ReflectClassBaseObject*, GetRuntimeTypeHelper(__me, typeHandle, keepAlive))
+
+NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive)
+{
+ FC_INNER_PROLOG_NO_ME_SETUP();
+ if (pModule == NULL)
+ return NULL;
+
+ DomainFile * pDomainFile = pModule->FindDomainFile(GetAppDomain());
+
+ OBJECTREF refModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
+
+ if(refModule != NULL)
+ return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
+
+ HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
+ refModule = pModule->GetExposedObject();
+ HELPER_METHOD_FRAME_END();
+
+ FC_INNER_EPILOG();
+ return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
+}
+
+NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive)
+{
+ FC_INNER_PROLOG_NO_ME_SETUP();
+ if (pAssembly == NULL)
+ return NULL;
+
+ OBJECTREF refAssembly = (pAssembly != NULL) ? pAssembly->GetExposedAssemblyObjectIfExists() : NULL;
+
+ if(refAssembly != NULL)
+ return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
+
+ HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
+ refAssembly = pAssembly->GetExposedAssemblyObject();
+ HELPER_METHOD_FRAME_END();
+
+ FC_INNER_EPILOG();
+ return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
+}
+
+
+// This is the routine that is called by the 'typeof()' operator in C#. It is one of the most commonly used
+// reflection operations. This call should be optimized away in nearly all situations
+FCIMPL1_V(ReflectClassBaseObject*, RuntimeTypeHandle::GetTypeFromHandle, FCALLRuntimeTypeHandle th)
+{
+ FCALL_CONTRACT;
+
+ FCUnique(0x31);
+ return FCALL_RTH_TO_REFLECTCLASS(th);
+}
+FCIMPLEND
+
+FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetRuntimeType, EnregisteredTypeHandle th)
+{
+ FCALL_CONTRACT;
+
+ TypeHandle typeHandle = TypeHandle::FromPtr(th);
+ _ASSERTE(CheckPointer(typeHandle.AsPtr(), NULL_OK));
+ if (typeHandle.AsPtr()!= NULL)
+ {
+ if (!typeHandle.IsTypeDesc())
+ {
+ OBJECTREF typePtr = typeHandle.AsMethodTable()->GetManagedClassObjectIfExists();
+ if (typePtr != NULL)
+ {
+ return (ReflectClassBaseObject*)OBJECTREFToObject(typePtr);
+ }
+ }
+ }
+ else
+ return NULL;
+
+ RETURN_CLASS_OBJECT(typeHandle, NULL);
+}
+FCIMPLEND
+
+FCIMPL1_V(EnregisteredTypeHandle, RuntimeTypeHandle::GetValueInternal, FCALLRuntimeTypeHandle RTH)
+{
+ FCALL_CONTRACT;
+
+ if (FCALL_RTH_TO_REFLECTCLASS(RTH) == NULL)
+ return 0;
+
+ return FCALL_RTH_TO_REFLECTCLASS(RTH) ->GetType().AsPtr();
+}
+FCIMPLEND
+
+// TypeEqualsHelper and TypeNotEqualsHelper are almost identical.
+// Unfortunately we cannot combime them because they need to hardcode the caller's name
+NOINLINE static BOOL TypeEqualSlow(OBJECTREF refL, OBJECTREF refR, LPVOID __me)
+{
+ BOOL ret = FALSE;
+
+ FC_INNER_PROLOG_NO_ME_SETUP();
+
+ _ASSERTE(refL != NULL && refR != NULL);
+
+ HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, refL, refR);
+
+ MethodDescCallSite TypeEqualsMethod(METHOD__OBJECT__EQUALS, &refL);
+
+ ARG_SLOT args[] =
+ {
+ ObjToArgSlot(refL),
+ ObjToArgSlot(refR)
+ };
+
+ ret = TypeEqualsMethod.Call_RetBool(args);
+
+ HELPER_METHOD_FRAME_END();
+
+ FC_INNER_EPILOG();
+
+ return ret;
+}
+
+
+
+#include <optsmallperfcritical.h>
+
+FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::TypeEQ, Object* left, Object* right)
+{
+ FCALL_CONTRACT;
+
+ OBJECTREF refL = (OBJECTREF)left;
+ OBJECTREF refR = (OBJECTREF)right;
+
+ if (refL == refR)
+ {
+ FC_RETURN_BOOL(TRUE);
+ }
+
+ if (!refL || !refR)
+ {
+ FC_RETURN_BOOL(FALSE);
+ }
+
+ if ((refL->GetMethodTable() == g_pRuntimeTypeClass || refR->GetMethodTable() == g_pRuntimeTypeClass))
+ {
+ // Quick path for negative common case
+ FC_RETURN_BOOL(FALSE);
+ }
+
+ // The fast path didn't get us the result
+ // Let's try the slow path: refL.Equals(refR);
+ FC_INNER_RETURN(FC_BOOL_RET, (FC_BOOL_RET)(!!TypeEqualSlow(refL, refR, __me)));
+}
+FCIMPLEND
+
+FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::TypeNEQ, Object* left, Object* right)
+{
+ FCALL_CONTRACT;
+
+ OBJECTREF refL = (OBJECTREF)left;
+ OBJECTREF refR = (OBJECTREF)right;
+
+ if (refL == refR)
+ {
+ FC_RETURN_BOOL(FALSE);
+ }
+
+ if (!refL || !refR)
+ {
+ FC_RETURN_BOOL(TRUE);
+ }
+
+ if ((refL->GetMethodTable() == g_pRuntimeTypeClass || refR->GetMethodTable() == g_pRuntimeTypeClass))
+ {
+ // Quick path for negative common case
+ FC_RETURN_BOOL(TRUE);
+ }
+
+ // The fast path didn't get us the result
+ // Let's try the slow path: refL.Equals(refR);
+ FC_INNER_RETURN(FC_BOOL_RET, (FC_BOOL_RET)(!TypeEqualSlow(refL, refR, __me)));
+}
+FCIMPLEND
+
+#include <optdefault.h>
+
+
+
+#ifndef FEATURE_CORECLR
+FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::IsEquivalentTo, ReflectClassBaseObject *rtType1UNSAFE, ReflectClassBaseObject *rtType2UNSAFE)
+{
+ FCALL_CONTRACT;
+
+ BOOL bResult = FALSE;
+
+ REFLECTCLASSBASEREF rtType1 = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(rtType1UNSAFE);
+ REFLECTCLASSBASEREF rtType2 = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(rtType2UNSAFE);
+
+ HELPER_METHOD_FRAME_BEGIN_RET_2(rtType1, rtType2);
+ if (rtType1 == NULL)
+ COMPlusThrowArgumentNull(W("rtType1"));
+ if (rtType2 == NULL)
+ COMPlusThrowArgumentNull(W("rtType2"));
+
+ bResult = rtType1->GetType().IsEquivalentTo(rtType2->GetType());
+ HELPER_METHOD_FRAME_END();
+
+ FC_RETURN_BOOL(bResult);
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsEquivalentType, ReflectClassBaseObject *rtTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ BOOL bResult = FALSE;
+
+ TypeHandle typeHandle = rtTypeUNSAFE->GetType();
+ if (!typeHandle.IsTypeDesc())
+ bResult = typeHandle.AsMethodTable()->GetClass()->IsEquivalentType();
+
+ FC_RETURN_BOOL(bResult);
+}
+FCIMPLEND
+#endif // !FEATURE_CORECLR
+
+#ifdef FEATURE_COMINTEROP
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsWindowsRuntimeObjectType, ReflectClassBaseObject *rtTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ BOOL isWindowsRuntimeType = FALSE;
+
+ TypeHandle typeHandle = rtTypeUNSAFE->GetType();
+ MethodTable *pMT = typeHandle.GetMethodTable();
+
+ if (pMT != NULL)
+ {
+ isWindowsRuntimeType = pMT->IsWinRTObjectType();
+ }
+
+ FC_RETURN_BOOL(isWindowsRuntimeType);
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsTypeExportedToWindowsRuntime, ReflectClassBaseObject *rtTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ BOOL isExportedToWinRT = FALSE;
+
+ TypeHandle typeHandle = rtTypeUNSAFE->GetType();
+ MethodTable *pMT = typeHandle.GetMethodTable();
+
+ if (pMT != NULL)
+ {
+ isExportedToWinRT = pMT->IsExportedToWinRT();
+ }
+
+ FC_RETURN_BOOL(isExportedToWinRT);
+}
+FCIMPLEND
+#endif // FEATURE_COMINTEROP
+
+NOINLINE static MethodDesc * RestoreMethodHelper(MethodDesc * pMethod, LPVOID __me)
+{
+ FC_INNER_PROLOG_NO_ME_SETUP();
+
+ HELPER_METHOD_FRAME_BEGIN_RET_0();
+ pMethod->CheckRestore();
+ HELPER_METHOD_FRAME_END();
+
+ FC_INNER_EPILOG();
+
+ return pMethod;
+}
+
+FCIMPL1(MethodDesc *, RuntimeTypeHandle::GetFirstIntroducedMethod, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(pTypeUNSAFE));
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+ TypeHandle typeHandle = refType->GetType();
+
+ if (typeHandle.IsGenericVariable())
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ if (typeHandle.IsTypeDesc()) {
+ if (!typeHandle.IsArray())
+ return NULL;
+ }
+
+ MethodTable* pMT = typeHandle.GetMethodTable();
+ if (pMT == NULL)
+ return NULL;
+
+ MethodDesc* pMethod = MethodTable::IntroducedMethodIterator::GetFirst(pMT);
+
+ // The only method that can show up here unrestored is instantiated methods. Check for it before performing the expensive IsRestored() check.
+ if (pMethod != NULL && pMethod->GetClassification() == mcInstantiated && !pMethod->IsRestored()) {
+ FC_INNER_RETURN(MethodDesc *, RestoreMethodHelper(pMethod, __me));
+ }
+
+ _ASSERTE(pMethod == NULL || pMethod->IsRestored());
+ return pMethod;
+}
+FCIMPLEND
+
+#include <optsmallperfcritical.h>
+FCIMPL1(void, RuntimeTypeHandle::GetNextIntroducedMethod, MethodDesc ** ppMethod) {
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(ppMethod));
+ PRECONDITION(CheckPointer(*ppMethod));
+ }
+ CONTRACTL_END;
+
+ MethodDesc *pMethod = MethodTable::IntroducedMethodIterator::GetNext(*ppMethod);
+
+ *ppMethod = pMethod;
+
+ if (pMethod != NULL && pMethod->GetClassification() == mcInstantiated && !pMethod->IsRestored()) {
+ FC_INNER_RETURN_VOID(RestoreMethodHelper(pMethod, __me));
+ }
+
+ _ASSERTE(pMethod == NULL || pMethod->IsRestored());
+}
+FCIMPLEND
+#include <optdefault.h>
+
+FCIMPL1(INT32, RuntimeTypeHandle::GetCorElementType, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ return refType->GetType().GetSignatureCorElementType();
+}
+FCIMPLEND
+
+FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssembly, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ DomainFile *pDomainFile = NULL;
+
+ Module *pModule = refType->GetType().GetAssembly()->GetManifestModule();
+
+ pDomainFile = pModule->FindDomainFile(GetAppDomain());
+#ifdef FEATURE_LOADER_OPTIMIZATION
+ if (pDomainFile == NULL)
+ {
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
+
+ pDomainFile = GetAppDomain()->LoadDomainNeutralModuleDependency(pModule, FILE_LOADED);
+
+ HELPER_METHOD_FRAME_END();
+ }
+#endif // FEATURE_LOADER_OPTIMIZATION
+
+
+ FC_RETURN_ASSEMBLY_OBJECT((DomainAssembly *)pDomainFile, refType);
+}
+FCIMPLEND
+
+
+FCIMPL1(FC_BOOL_RET, RuntimeFieldHandle::AcquiresContextFromThis, FieldDesc *pField)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(pField));
+ }
+ CONTRACTL_END;
+
+ FC_RETURN_BOOL(pField->IsSharedByGenericInstantiations());
+
+}
+FCIMPLEND
+
+// static
+BOOL QCALLTYPE RuntimeFieldHandle::IsSecurityCritical(FieldDesc *pFD)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pFD));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsCritical = FALSE;
+
+ BEGIN_QCALL;
+
+ fIsCritical = Security::IsFieldCritical(pFD);
+
+ END_QCALL;
+
+ return fIsCritical;
+}
+
+// static
+BOOL QCALLTYPE RuntimeFieldHandle::IsSecuritySafeCritical(FieldDesc *pFD)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pFD));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsSafeCritical = FALSE;
+
+ BEGIN_QCALL;
+
+ fIsSafeCritical = Security::IsFieldSafeCritical(pFD);
+
+ END_QCALL;
+
+ return fIsSafeCritical;
+}
+
+// static
+BOOL QCALLTYPE RuntimeFieldHandle::IsSecurityTransparent(FieldDesc *pFD)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pFD));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsTransparent = FALSE;
+
+ BEGIN_QCALL;
+
+ fIsTransparent = Security::IsFieldTransparent(pFD);
+
+ END_QCALL;
+
+ return fIsTransparent;
+}
+
+// static
+void QCALLTYPE RuntimeFieldHandle::CheckAttributeAccess(FieldDesc *pFD, QCall::ModuleHandle pModule)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pFD));
+ PRECONDITION(CheckPointer(pModule.m_pModule));
+ }
+ CONTRACTL_END;
+
+ if(!Security::IsTransparencyEnforcementEnabled())
+ {
+ FCUnique(0xb1);
+ return;
+ }
+
+ BEGIN_QCALL;
+
+ if (Security::IsFieldCritical(pFD) && !Security::IsFieldSafeCritical(pFD))
+ {
+ GCX_COOP();
+
+ if (!DoAttributeTransparencyChecks(pFD->GetModule()->GetAssembly(), pModule->GetAssembly()))
+ {
+ ThrowFieldAccessException(NULL, pFD, TRUE, IDS_E_CRITICAL_FIELD_ACCESS_DENIED);
+ }
+ }
+
+ END_QCALL;
+}
+
+FCIMPL1(ReflectModuleBaseObject*, RuntimeTypeHandle::GetModule, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ Module *result;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
+
+ result = refType->GetType().GetModule();
+
+ END_SO_INTOLERANT_CODE;
+
+ FC_RETURN_MODULE_OBJECT(result, refType);
+}
+FCIMPLEND
+
+FCIMPL1(ReflectClassBaseObject *, RuntimeTypeHandle::GetBaseType, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ if (typeHandle.IsGenericVariable())
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ if (typeHandle.IsTypeDesc()) {
+ if (!typeHandle.IsArray())
+ return NULL;
+ }
+
+ RETURN_CLASS_OBJECT(typeHandle.GetParent(), refType);
+}
+FCIMPLEND
+
+FCIMPL1(ReflectClassBaseObject *, RuntimeTypeHandle::GetElementType, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ if (!typeHandle.IsTypeDesc())
+ return 0;
+
+ if (typeHandle.IsGenericVariable())
+ return 0;
+
+ TypeHandle typeReturn;
+
+ if (typeHandle.IsArray())
+ typeReturn = typeHandle.AsArray()->GetArrayElementTypeHandle();
+ else
+ typeReturn = typeHandle.AsTypeDesc()->GetTypeParam();
+
+ RETURN_CLASS_OBJECT(typeReturn, refType);
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeTypeHandle::GetArrayRank, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(pTypeUNSAFE));
+ PRECONDITION(pTypeUNSAFE->GetType().IsArray());
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ return (INT32)refType->GetType().AsArray()->GetRank();
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeTypeHandle::GetNumVirtuals, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ if (typeHandle.IsGenericVariable())
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ MethodTable *pMT = typeHandle.GetMethodTable();
+
+ if (pMT)
+ return (INT32)pMT->GetNumVirtuals();
+ else
+ return 0; //REVIEW: should this return the number of methods in Object?
+}
+FCIMPLEND
+
+FCIMPL2(MethodDesc *, RuntimeTypeHandle::GetMethodAt, ReflectClassBaseObject *pTypeUNSAFE, INT32 slot) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ MethodDesc* pRetMethod = NULL;
+
+ if (typeHandle.IsGenericVariable())
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ if (slot < 0 || slot >= (INT32)typeHandle.GetMethodTable()->GetNumVirtuals())
+ FCThrowRes(kArgumentException, W("Arg_ArgumentOutOfRangeException"));
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
+ pRetMethod = typeHandle.GetMethodTable()->GetMethodDescForSlot((DWORD)slot);
+ HELPER_METHOD_FRAME_END();
+
+ return pRetMethod;
+}
+
+FCIMPLEND
+
+FCIMPL3(FC_BOOL_RET, RuntimeTypeHandle::GetFields, ReflectClassBaseObject *pTypeUNSAFE, INT32 **result, INT32 *pCount) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ if (!pCount || !result)
+ FCThrow(kArgumentNullException);
+
+ if (typeHandle.IsGenericVariable())
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ if (typeHandle.IsTypeDesc()) {
+ *pCount = 0;
+ FC_RETURN_BOOL(TRUE);
+ }
+
+ MethodTable *pMT= typeHandle.GetMethodTable();
+ if (!pMT)
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ BOOL retVal = FALSE;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
+ // <TODO>Check this approximation - we may be losing exact type information </TODO>
+ ApproxFieldDescIterator fdIterator(pMT, ApproxFieldDescIterator::ALL_FIELDS);
+ INT32 count = (INT32)fdIterator.Count();
+
+ if (count > *pCount)
+ {
+ *pCount = count;
+ }
+ else
+ {
+ for(INT32 i = 0; i < count; i ++)
+ result[i] = (INT32*)fdIterator.Next();
+
+ *pCount = count;
+ retVal = TRUE;
+ }
+ HELPER_METHOD_FRAME_END();
+ FC_RETURN_BOOL(retVal);
+}
+FCIMPLEND
+
+void QCALLTYPE RuntimeMethodHandle::ConstructInstantiation(MethodDesc * pMethod, DWORD format, QCall::StringHandleOnStack retString)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ StackSString ss;
+ TypeString::AppendInst(ss, pMethod->LoadMethodInstantiation(), format);
+ retString.Set(ss);
+
+ END_QCALL;
+}
+
+void QCALLTYPE RuntimeTypeHandle::ConstructName(EnregisteredTypeHandle pTypeHandle, DWORD format, QCall::StringHandleOnStack retString)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ StackSString ss;
+ TypeString::AppendType(ss, TypeHandle::FromPtr(pTypeHandle), format);
+ retString.Set(ss);
+
+ END_QCALL;
+}
+
+PTRARRAYREF CopyRuntimeTypeHandles(TypeHandle * prgTH, FixupPointer<TypeHandle> * prgTH2, INT32 numTypeHandles, BinderClassID arrayElemType)
+{
+ CONTRACTL {
+ THROWS;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ PTRARRAYREF refReturn = NULL;
+ PTRARRAYREF refArray = NULL;
+
+ if (numTypeHandles == 0)
+ return NULL;
+
+ _ASSERTE((prgTH != NULL) || (prgTH2 != NULL));
+ if (prgTH != NULL)
+ {
+ _ASSERTE(prgTH2 == NULL);
+ }
+
+ GCPROTECT_BEGIN(refArray);
+ TypeHandle thRuntimeType = TypeHandle(MscorlibBinder::GetClass(arrayElemType));
+ TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(thRuntimeType, ELEMENT_TYPE_SZARRAY);
+ refArray = (PTRARRAYREF)AllocateArrayEx(arrayHandle, &numTypeHandles, 1);
+
+ for (INT32 i = 0; i < numTypeHandles; i++)
+ {
+ TypeHandle th;
+
+ if (prgTH != NULL)
+ th = prgTH[i];
+ else
+ th = prgTH2[i].GetValue();
+
+ OBJECTREF refType = th.GetManagedClassObject();
+ refArray->SetAt(i, refType);
+ }
+
+ refReturn = refArray;
+ GCPROTECT_END();
+
+ return refReturn;
+}
+
+void QCALLTYPE RuntimeTypeHandle::GetConstraints(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retTypeArray)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle* constraints = NULL;
+
+ BEGIN_QCALL;
+
+ TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
+
+ if (!typeHandle.IsGenericVariable())
+ COMPlusThrow(kArgumentException, W("Arg_InvalidHandle"));
+
+ TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();
+
+ DWORD dwCount;
+ constraints = pGenericVariable->GetConstraints(&dwCount);
+
+ GCX_COOP();
+ retTypeArray.Set(CopyRuntimeTypeHandles(constraints, NULL, dwCount, CLASS__TYPE));
+
+ END_QCALL;
+
+ return;
+}
+
+FCIMPL1(PtrArray*, RuntimeTypeHandle::GetInterfaces, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ if (typeHandle.IsGenericVariable())
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ INT32 ifaceCount = 0;
+
+ PTRARRAYREF refRetVal = NULL;
+ HELPER_METHOD_FRAME_BEGIN_RET_2(refRetVal, refType);
+ {
+ if (typeHandle.IsTypeDesc())
+ {
+ if (typeHandle.IsArray())
+ {
+ ifaceCount = typeHandle.GetMethodTable()->GetNumInterfaces();
+ }
+ else
+ {
+ ifaceCount = 0;
+ }
+ }
+ else
+ {
+ ifaceCount = typeHandle.GetMethodTable()->GetNumInterfaces();
+ }
+
+ // Allocate the array
+ if (ifaceCount > 0)
+ {
+ TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pRuntimeTypeClass), ELEMENT_TYPE_SZARRAY);
+ refRetVal = (PTRARRAYREF)AllocateArrayEx(arrayHandle, &ifaceCount, 1);
+
+ // populate type array
+ UINT i = 0;
+
+ MethodTable::InterfaceMapIterator it = typeHandle.GetMethodTable()->IterateInterfaceMap();
+ while (it.Next())
+ {
+ OBJECTREF refInterface = it.GetInterface()->GetManagedClassObject();
+ refRetVal->SetAt(i, refInterface);
+ _ASSERTE(refRetVal->GetAt(i) != NULL);
+ i++;
+ }
+ }
+ }
+ HELPER_METHOD_FRAME_END();
+
+ return (PtrArray*)OBJECTREFToObject(refRetVal);
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeTypeHandle::GetAttributes, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ if (typeHandle.IsTypeDesc()) {
+
+ if (typeHandle.IsGenericVariable()) {
+ return tdPublic;
+ }
+
+ if (!typeHandle.IsArray())
+ return 0;
+ }
+
+#ifdef FEATURE_COMINTEROP
+ // __ComObject types are always public.
+ if (IsComObjectClass(typeHandle))
+ return (typeHandle.GetMethodTable()->GetAttrClass() & tdVisibilityMask) | tdPublic;
+#endif // FEATURE_COMINTEROP
+
+ INT32 ret = 0;
+
+ ret = (INT32)typeHandle.GetMethodTable()->GetAttrClass();
+ return ret;
+}
+FCIMPLEND
+
+#ifdef FEATURE_REMOTING
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsContextful, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ if (typeHandle.IsTypeDesc())
+ FC_RETURN_BOOL(FALSE);
+
+ MethodTable* pMT= typeHandle.GetMethodTable();
+
+ if (!pMT)
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ FC_RETURN_BOOL(pMT->IsContextful());
+}
+FCIMPLEND
+#endif
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsValueType, ReflectClassBaseObject *pTypeUNSAFE)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ _ASSERTE(refType != NULL);
+
+ TypeHandle typeHandle = refType->GetType();
+
+ FC_RETURN_BOOL(typeHandle.IsValueType());
+}
+FCIMPLEND;
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsInterface, ReflectClassBaseObject *pTypeUNSAFE)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ _ASSERTE(refType != NULL);
+
+ TypeHandle typeHandle = refType->GetType();
+
+ FC_RETURN_BOOL(typeHandle.IsInterface());
+}
+FCIMPLEND;
+
+BOOL
+QCALLTYPE
+RuntimeTypeHandle::IsVisible(
+ EnregisteredTypeHandle pTypeHandle)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ BOOL fIsExternallyVisible = FALSE;
+
+ BEGIN_QCALL;
+
+ TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
+
+ _ASSERTE(!typeHandle.IsNull());
+
+ fIsExternallyVisible = typeHandle.IsExternallyVisible();
+
+ END_QCALL;
+
+ return fIsExternallyVisible;
+} // RuntimeTypeHandle::IsVisible
+
+// static
+BOOL QCALLTYPE RuntimeTypeHandle::IsSecurityCritical(EnregisteredTypeHandle pTypeHandle)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pTypeHandle));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsCritical = FALSE;
+
+ BEGIN_QCALL;
+
+ MethodTable *pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
+ if (pMT != NULL)
+ {
+ fIsCritical = Security::IsTypeCritical(pMT);
+ }
+
+ END_QCALL;
+
+ return fIsCritical;
+}
+
+// static
+BOOL QCALLTYPE RuntimeTypeHandle::IsSecuritySafeCritical(EnregisteredTypeHandle pTypeHandle)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pTypeHandle));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsSafeCritical = FALSE;
+
+ BEGIN_QCALL;
+
+ MethodTable *pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
+ if (pMT != NULL)
+ {
+ fIsSafeCritical = Security::IsTypeSafeCritical(pMT);
+ }
+
+ END_QCALL;
+
+ return fIsSafeCritical;
+}
+
+// static
+BOOL QCALLTYPE RuntimeTypeHandle::IsSecurityTransparent(EnregisteredTypeHandle pTypeHandle)
+{
+ CONTRACTL
+ {
+ QCALL_CHECK;
+ PRECONDITION(CheckPointer(pTypeHandle));
+ }
+ CONTRACTL_END;
+
+ BOOL fIsTransparent = TRUE;
+
+ BEGIN_QCALL;
+
+ MethodTable * pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
+ if (pMT != NULL)
+ {
+ fIsTransparent = Security::IsTypeTransparent(pMT);
+ }
+
+ END_QCALL;
+
+ return fIsTransparent;
+}
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::HasProxyAttribute, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ // TODO: Justify this
+ if (typeHandle.IsGenericVariable())
+ FC_RETURN_BOOL(FALSE);
+
+ if (typeHandle.IsTypeDesc()) {
+ if (!typeHandle.IsArray())
+ FC_RETURN_BOOL(FALSE);
+ }
+
+ MethodTable* pMT= typeHandle.GetMethodTable();
+
+ if (!pMT)
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ FC_RETURN_BOOL(pMT->GetClass()->HasRemotingProxyAttribute());
+}
+FCIMPLEND
+
+FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::IsComObject, ReflectClassBaseObject *pTypeUNSAFE, CLR_BOOL isGenericCOM) {
+#ifdef FEATURE_COMINTEROP
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ BOOL ret = FALSE;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
+ {
+ if (isGenericCOM)
+ ret = IsComObjectClass(typeHandle);
+ else
+ ret = IsComWrapperClass(typeHandle);
+ }
+ HELPER_METHOD_FRAME_END();
+
+ FC_RETURN_BOOL(ret);
+#else
+ CONTRACTL {
+ DISABLED(NOTHROW);
+ GC_NOTRIGGER;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(pTypeUNSAFE));
+ }
+ CONTRACTL_END;
+ FCUnique(0x37);
+ FC_RETURN_BOOL(FALSE);
+#endif
+}
+FCIMPLEND
+
+FCIMPL1(LPCUTF8, RuntimeTypeHandle::GetUtf8Name, ReflectClassBaseObject* pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+ INT32 tkTypeDef = mdTypeDefNil;
+ LPCUTF8 szName = NULL;
+
+ if (typeHandle.IsGenericVariable())
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ if (typeHandle.IsTypeDesc())
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ MethodTable* pMT= typeHandle.GetMethodTable();
+
+ if (pMT == NULL)
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ tkTypeDef = (INT32)pMT->GetCl();
+
+ if (IsNilToken(tkTypeDef))
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ if (FAILED(pMT->GetMDImport()->GetNameOfTypeDef(tkTypeDef, &szName, NULL)))
+ {
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+ }
+
+ _ASSERTE(CheckPointer(szName, NULL_OK));
+
+ return szName;
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeTypeHandle::GetToken, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ if (typeHandle.IsTypeDesc())
+ {
+ if (typeHandle.IsGenericVariable())
+ {
+ INT32 tkTypeDef = typeHandle.AsGenericVariable()->GetToken();
+
+ _ASSERTE(!IsNilToken(tkTypeDef) && TypeFromToken(tkTypeDef) == mdtGenericParam);
+
+ return tkTypeDef;
+ }
+
+ return mdTypeDefNil;
+ }
+
+ return (INT32)typeHandle.AsMethodTable()->GetCl();
+}
+FCIMPLEND
+
+PVOID QCALLTYPE RuntimeTypeHandle::GetGCHandle(EnregisteredTypeHandle pTypeHandle, INT32 handleType)
+{
+ QCALL_CONTRACT;
+
+ OBJECTHANDLE objHandle = NULL;
+
+ BEGIN_QCALL;
+
+ GCX_COOP();
+
+ TypeHandle th = TypeHandle::FromPtr(pTypeHandle);
+ objHandle = th.GetDomain()->CreateTypedHandle(NULL, handleType);
+ th.GetLoaderAllocator()->RegisterHandleForCleanup(objHandle);
+
+ END_QCALL;
+
+ return objHandle;
+}
+
+void QCALLTYPE RuntimeTypeHandle::VerifyInterfaceIsImplemented(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pIFaceHandle)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
+ TypeHandle ifaceHandle = TypeHandle::FromPtr(pIFaceHandle);
+
+ if (typeHandle.IsGenericVariable())
+ COMPlusThrow(kArgumentException, W("Arg_InvalidHandle"));
+
+ if (typeHandle.IsTypeDesc()) {
+ if (!typeHandle.IsArray())
+ COMPlusThrow(kArgumentException, W("Arg_NotFoundIFace"));
+ }
+
+ if (typeHandle.IsInterface())
+ COMPlusThrow(kArgumentException, W("Argument_InterfaceMap"));
+
+ if (!ifaceHandle.IsInterface())
+ COMPlusThrow(kArgumentException, W("Arg_MustBeInterface"));
+
+ // First try the cheap check, which amounts to iterating the interface map looking for
+ // the ifaceHandle MethodTable.
+ if (!typeHandle.GetMethodTable()->ImplementsInterface(ifaceHandle.AsMethodTable()))
+ { // If the cheap check fails, try the more expensive but complete check.
+ if (!typeHandle.CanCastTo(ifaceHandle))
+ { // If the complete check fails, we're certain that this type
+ // does not implement the interface specified.
+ COMPlusThrow(kArgumentException, W("Arg_NotFoundIFace"));
+ }
+ }
+
+ END_QCALL;
+}
+
+INT32 QCALLTYPE RuntimeTypeHandle::GetInterfaceMethodImplementationSlot(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pOwner, MethodDesc * pMD)
+{
+ QCALL_CONTRACT;
+
+ INT32 slotNumber = -1;
+
+ BEGIN_QCALL;
+
+ TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
+ TypeHandle thOwnerOfMD = TypeHandle::FromPtr(pOwner);
+
+ // Ok to have INVALID_SLOT in the case where abstract class does not implement an interface method.
+ // This case can not be reproed using C# "implements" all interface methods
+ // with at least an abstract method. b19897_GetInterfaceMap_Abstract.exe tests this case.
+ //@TODO:STUBDISPATCH: Don't need to track down the implementation, just the declaration, and this can
+ //@TODO: be done faster - just need to make a function FindDispatchDecl.
+ DispatchSlot slot(typeHandle.GetMethodTable()->FindDispatchSlotForInterfaceMD(thOwnerOfMD, pMD));
+ if (!slot.IsNull())
+ slotNumber = slot.GetMethodDesc()->GetSlot();
+
+ END_QCALL;
+
+ return slotNumber;
+ }
+
+void QCALLTYPE RuntimeTypeHandle::GetDefaultConstructor(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retMethod)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ MethodDesc* pCtor = NULL;
+
+ TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
+
+ if (!typeHandle.IsTypeDesc())
+ {
+ MethodTable* pMethodTable = typeHandle.AsMethodTable();
+ if (pMethodTable->HasDefaultConstructor())
+ pCtor = pMethodTable->GetDefaultConstructor();
+ }
+
+ if (pCtor != NULL)
+ {
+ GCX_COOP();
+ retMethod.Set(pCtor->GetStubMethodInfo());
+ }
+ END_QCALL;
+
+ return;
+}
+
+FCIMPL1(ReflectMethodObject*, RuntimeTypeHandle::GetDeclaringMethod, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();;
+
+ if (!typeHandle.IsTypeDesc())
+ return NULL;
+
+ TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();
+ mdToken defToken = pGenericVariable->GetTypeOrMethodDef();
+ if (TypeFromToken(defToken) != mdtMethodDef)
+ return NULL;
+
+ REFLECTMETHODREF pRet = NULL;
+ HELPER_METHOD_FRAME_BEGIN_RET_0();
+ MethodDesc * pMD = pGenericVariable->LoadOwnerMethod();
+ pMD->CheckRestore();
+ pRet = pMD->GetStubMethodInfo();
+ HELPER_METHOD_FRAME_END();
+
+ return (ReflectMethodObject*)OBJECTREFToObject(pRet);
+}
+FCIMPLEND
+
+FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetDeclaringType, ReflectClassBaseObject *pTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ TypeHandle retTypeHandle;
+
+ BOOL fThrowException = FALSE;
+ LPCWSTR argName = W("Arg_InvalidHandle");
+ RuntimeExceptionKind reKind = kArgumentNullException;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle typeHandle = refType->GetType();
+
+ MethodTable* pMT = NULL;
+ mdTypeDef tkTypeDef = mdTokenNil;
+
+ BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
+ if (typeHandle.IsTypeDesc()) {
+
+ if (typeHandle.IsGenericVariable()) {
+ TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();
+ mdToken defToken = pGenericVariable->GetTypeOrMethodDef();
+
+ // Try the fast way first (if the declaring type has been loaded already).
+ if (TypeFromToken(defToken) == mdtMethodDef)
+ {
+ MethodDesc * retMethod = pGenericVariable->GetModule()->LookupMethodDef(defToken);
+ if (retMethod != NULL)
+ retTypeHandle = retMethod->GetMethodTable();
+ }
+ else
+ {
+ retTypeHandle = pGenericVariable->GetModule()->LookupTypeDef(defToken);
+ }
+
+ if (!retTypeHandle.IsNull() && retTypeHandle.IsFullyLoaded())
+ goto Exit;
+
+ // OK, need to go the slow way and load the type first.
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
+ {
+ if (TypeFromToken(defToken) == mdtMethodDef)
+ {
+ retTypeHandle = pGenericVariable->LoadOwnerMethod()->GetMethodTable();
+ }
+ else
+ {
+ retTypeHandle = pGenericVariable->LoadOwnerType();
+ }
+ retTypeHandle.CheckRestore();
+ }
+ HELPER_METHOD_FRAME_END();
+ goto Exit;
+ }
+ if (!typeHandle.IsArray())
+ {
+ retTypeHandle = TypeHandle();
+ goto Exit;
+ }
+ }
+
+ pMT = typeHandle.GetMethodTable();
+
+ if (pMT == NULL)
+ {
+ fThrowException = TRUE;
+ goto Exit;
+ }
+
+ if(!pMT->GetClass()->IsNested())
+ {
+ retTypeHandle = TypeHandle();
+ goto Exit;
+ }
+
+ tkTypeDef = pMT->GetCl();
+
+ if (FAILED(typeHandle.GetModule()->GetMDImport()->GetNestedClassProps(tkTypeDef, &tkTypeDef)))
+ {
+ fThrowException = TRUE;
+ reKind = kBadImageFormatException;
+ argName = NULL;
+ goto Exit;
+ }
+
+ // Try the fast way first (if the declaring type has been loaded already).
+ retTypeHandle = typeHandle.GetModule()->LookupTypeDef(tkTypeDef);
+ if (retTypeHandle.IsNull())
+ {
+ // OK, need to go the slow way and load the type first.
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
+ {
+ retTypeHandle = ClassLoader::LoadTypeDefThrowing(typeHandle.GetModule(), tkTypeDef,
+ ClassLoader::ThrowIfNotFound,
+ ClassLoader::PermitUninstDefOrRef);
+ }
+ HELPER_METHOD_FRAME_END();
+ }
+Exit:
+
+ END_SO_INTOLERANT_CODE;
+
+ if (fThrowException)
+ {
+ FCThrowRes(reKind, argName);
+ }
+
+ RETURN_CLASS_OBJECT(retTypeHandle, refType);
+ }
+FCIMPLEND
+
+FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::CanCastTo, ReflectClassBaseObject *pTypeUNSAFE, ReflectClassBaseObject *pTargetUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+ REFLECTCLASSBASEREF refTarget = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTargetUNSAFE);
+
+ if ((refType == NULL) || (refTarget == NULL))
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle fromHandle = refType->GetType();
+ TypeHandle toHandle = refTarget->GetType();
+
+ BOOL iRetVal = 0;
+
+ TypeHandle::CastResult r = fromHandle.CanCastToNoGC(toHandle);
+ if (r == TypeHandle::MaybeCast)
+ {
+ HELPER_METHOD_FRAME_BEGIN_RET_2(refType, refTarget);
+ iRetVal = fromHandle.CanCastTo(toHandle);
+ HELPER_METHOD_FRAME_END();
+ }
+ else
+ {
+ iRetVal = (r == TypeHandle::CanCast);
+ }
+
+ // We allow T to be cast to Nullable<T>
+ if (!iRetVal && Nullable::IsNullableType(toHandle) && !fromHandle.IsTypeDesc())
+ {
+ HELPER_METHOD_FRAME_BEGIN_RET_2(refType, refTarget);
+ if (Nullable::IsNullableForType(toHandle, fromHandle.AsMethodTable()))
+ {
+ iRetVal = TRUE;
+ }
+ HELPER_METHOD_FRAME_END();
+ }
+
+ FC_RETURN_BOOL(iRetVal);
+}
+FCIMPLEND
+
+void QCALLTYPE RuntimeTypeHandle::GetTypeByNameUsingCARules(LPCWSTR pwzClassName, QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle typeHandle;
+
+ BEGIN_QCALL;
+
+ if (!pwzClassName)
+ COMPlusThrowArgumentNull(W("className"),W("ArgumentNull_String"));
+
+ typeHandle = TypeName::GetTypeUsingCASearchRules(pwzClassName, pModule->GetAssembly());
+
+ GCX_COOP();
+ retType.Set(typeHandle.GetManagedClassObject());
+
+ END_QCALL;
+
+ return;
+}
+
+void QCALLTYPE RuntimeTypeHandle::GetTypeByName(LPCWSTR pwzClassName, BOOL bThrowOnError, BOOL bIgnoreCase, BOOL bReflectionOnly,
+ QCall::StackCrawlMarkHandle pStackMark,
+ ICLRPrivBinder * pPrivHostBinder,
+ BOOL bLoadTypeFromPartialNameHack, QCall::ObjectHandleOnStack retType,
+ QCall::ObjectHandleOnStack keepAlive)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle typeHandle;
+
+ BEGIN_QCALL;
+
+ if (!pwzClassName)
+ COMPlusThrowArgumentNull(W("className"),W("ArgumentNull_String"));
+
+ {
+ typeHandle = TypeName::GetTypeManaged(pwzClassName, NULL, bThrowOnError, bIgnoreCase, bReflectionOnly, /*bProhibitAsmQualifiedName =*/ FALSE, pStackMark,
+ bLoadTypeFromPartialNameHack, (OBJECTREF*)keepAlive.m_ppObject,
+ pPrivHostBinder);
+ }
+
+ if (!typeHandle.IsNull())
+ {
+ GCX_COOP();
+ retType.Set(typeHandle.GetManagedClassObject());
+ }
+
+ END_QCALL;
+
+ return;
+}
+
+FCIMPL6(FC_BOOL_RET, RuntimeTypeHandle::SatisfiesConstraints, PTR_ReflectClassBaseObject pParamTypeUNSAFE, TypeHandle *typeContextArgs, INT32 typeContextCount, TypeHandle *methodContextArgs, INT32 methodContextCount, PTR_ReflectClassBaseObject pArgumentTypeUNSAFE);
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(typeContextArgs, NULL_OK));
+ PRECONDITION(CheckPointer(methodContextArgs, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refParamType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pParamTypeUNSAFE);
+ REFLECTCLASSBASEREF refArgumentType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pArgumentTypeUNSAFE);
+
+ TypeHandle thGenericParameter = refParamType->GetType();
+ TypeHandle thGenericArgument = refArgumentType->GetType();
+ BOOL bResult = FALSE;
+ SigTypeContext typeContext;
+
+ Instantiation classInst;
+ Instantiation methodInst;
+
+ if (typeContextArgs != NULL)
+ {
+ classInst = Instantiation(typeContextArgs, typeContextCount);
+ }
+
+ if (methodContextArgs != NULL)
+ {
+ methodInst = Instantiation(methodContextArgs, methodContextCount);
+ }
+
+ SigTypeContext::InitTypeContext(classInst, methodInst, &typeContext);
+
+ HELPER_METHOD_FRAME_BEGIN_RET_2(refParamType, refArgumentType);
+ {
+ bResult = thGenericParameter.AsGenericVariable()->SatisfiesConstraints(&typeContext, thGenericArgument);
+ }
+ HELPER_METHOD_FRAME_END();
+
+ FC_RETURN_BOOL(bResult);
+}
+FCIMPLEND
+
+void QCALLTYPE RuntimeTypeHandle::GetInstantiation(EnregisteredTypeHandle pType, QCall::ObjectHandleOnStack retTypes, BOOL fAsRuntimeTypeArray)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ TypeHandle typeHandle = TypeHandle::FromPtr(pType);
+ Instantiation inst = typeHandle.GetInstantiation();
+ GCX_COOP();
+ retTypes.Set(CopyRuntimeTypeHandles(NULL, inst.GetRawArgs(), inst.GetNumArgs(), fAsRuntimeTypeArray ? CLASS__CLASS : CLASS__TYPE));
+ END_QCALL;
+
+ return;
+}
+
+void QCALLTYPE RuntimeTypeHandle::MakeArray(EnregisteredTypeHandle pTypeHandle, INT32 rank, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle arrayHandle;
+
+ BEGIN_QCALL;
+ arrayHandle = TypeHandle::FromPtr(pTypeHandle).MakeArray(rank);
+ GCX_COOP();
+ retType.Set(arrayHandle.GetManagedClassObject());
+ END_QCALL;
+
+ return;
+}
+
+void QCALLTYPE RuntimeTypeHandle::MakeSZArray(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle arrayHandle;
+
+ BEGIN_QCALL;
+ arrayHandle = TypeHandle::FromPtr(pTypeHandle).MakeSZArray();
+ GCX_COOP();
+ retType.Set(arrayHandle.GetManagedClassObject());
+ END_QCALL;
+
+ return;
+}
+
+void QCALLTYPE RuntimeTypeHandle::MakePointer(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle pointerHandle;
+
+ BEGIN_QCALL;
+ pointerHandle = TypeHandle::FromPtr(pTypeHandle).MakePointer();
+ GCX_COOP();
+ retType.Set(pointerHandle.GetManagedClassObject());
+ END_QCALL;
+
+ return;
+}
+
+void QCALLTYPE RuntimeTypeHandle::MakeByRef(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle byRefHandle;
+
+ BEGIN_QCALL;
+ byRefHandle = TypeHandle::FromPtr(pTypeHandle).MakeByRef();
+ GCX_COOP();
+ retType.Set(byRefHandle.GetManagedClassObject());
+ END_QCALL;
+
+ return;
+}
+
+BOOL QCALLTYPE RuntimeTypeHandle::IsCollectible(EnregisteredTypeHandle pTypeHandle)
+{
+ QCALL_CONTRACT;
+
+ BOOL retVal = FALSE;
+
+ BEGIN_QCALL;
+ retVal = TypeHandle::FromPtr(pTypeHandle).GetLoaderAllocator()->IsCollectible();
+ END_QCALL;
+
+ return retVal;
+}
+
+void QCALLTYPE RuntimeTypeHandle::Instantiate(EnregisteredTypeHandle pTypeHandle, TypeHandle * pInstArray, INT32 cInstArray, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle type;
+
+ BEGIN_QCALL;
+ type = TypeHandle::FromPtr(pTypeHandle).Instantiate(Instantiation(pInstArray, cInstArray));
+ GCX_COOP();
+ retType.Set(type.GetManagedClassObject());
+ END_QCALL;
+
+ return;
+}
+
+void QCALLTYPE RuntimeTypeHandle::GetGenericTypeDefinition(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle typeDef;
+
+ BEGIN_QCALL;
+
+ TypeHandle genericType = TypeHandle::FromPtr(pTypeHandle);
+
+ typeDef = ClassLoader::LoadTypeDefThrowing(genericType.GetModule(),
+ genericType.GetMethodTable()->GetCl(),
+ ClassLoader::ThrowIfNotFound,
+ ClassLoader::PermitUninstDefOrRef);
+
+ GCX_COOP();
+ retType.Set(typeDef.GetManagedClassObject());
+
+ END_QCALL;
+
+ return;
+}
+
+FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::CompareCanonicalHandles, ReflectClassBaseObject *pLeftUNSAFE, ReflectClassBaseObject *pRightUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTCLASSBASEREF refLeft = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pLeftUNSAFE);
+ REFLECTCLASSBASEREF refRight = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pRightUNSAFE);
+
+ if ((refLeft == NULL) || (refRight == NULL))
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ FC_RETURN_BOOL(refLeft->GetType().GetCanonicalMethodTable() == refRight->GetType().GetCanonicalMethodTable());
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::HasInstantiation, PTR_ReflectClassBaseObject pTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ FC_RETURN_BOOL(refType->GetType().HasInstantiation());
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsGenericTypeDefinition, PTR_ReflectClassBaseObject pTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ FC_RETURN_BOOL(refType->GetType().IsGenericTypeDefinition());
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsGenericVariable, PTR_ReflectClassBaseObject pTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ FC_RETURN_BOOL(refType->GetType().IsGenericVariable());
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeTypeHandle::GetGenericVariableIndex, PTR_ReflectClassBaseObject pTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ return (INT32)refType->GetType().AsGenericVariable()->GetIndex();
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::ContainsGenericVariables, PTR_ReflectClassBaseObject pTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ FC_RETURN_BOOL(refType->GetType().ContainsGenericVariables());
+}
+FCIMPLEND
+
+FCIMPL1(IMDInternalImport*, RuntimeTypeHandle::GetMetadataImport, ReflectClassBaseObject * pTypeUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ Module *pModule = refType->GetType().GetModule();
+
+ return pModule->GetMDImport();
+}
+FCIMPLEND
+
+
+//***********************************************************************************
+//***********************************************************************************
+//***********************************************************************************
+
+void * QCALLTYPE RuntimeMethodHandle::GetFunctionPointer(MethodDesc * pMethod)
+{
+ QCALL_CONTRACT;
+
+ void* funcPtr = 0;
+
+ BEGIN_QCALL;
+
+ funcPtr = (void*)pMethod->GetMultiCallableAddrOfCode();
+
+ END_QCALL;
+
+ return funcPtr;
+}
+
+FCIMPL1(LPCUTF8, RuntimeMethodHandle::GetUtf8Name, MethodDesc *pMethod) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ LPCUTF8 szName = NULL;
+
+ if (!pMethod)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ szName = pMethod->GetName();
+
+ _ASSERTE(CheckPointer(szName, NULL_OK));
+
+ return szName;
+}
+FCIMPLEND
+
+FCIMPL2(FC_BOOL_RET, RuntimeMethodHandle::MatchesNameHash, MethodDesc * pMethod, ULONG hash)
+{
+ FCALL_CONTRACT;
+
+ FC_RETURN_BOOL(pMethod->MightHaveName(hash));
+}
+FCIMPLEND
+
+FCIMPL1(StringObject*, RuntimeMethodHandle::GetName, MethodDesc *pMethod) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ if (!pMethod)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ STRINGREF refName = NULL;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_0();
+ refName = StringObject::NewString(pMethod->GetName());
+ HELPER_METHOD_FRAME_END();
+
+ return (StringObject*)OBJECTREFToObject(refName);
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeMethodHandle::GetAttributes, MethodDesc *pMethod) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ if (!pMethod)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ INT32 retVal = 0;
+ BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
+ retVal = (INT32)pMethod->GetAttrs();
+ END_SO_INTOLERANT_CODE;
+ return retVal;
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeMethodHandle::GetImplAttributes, ReflectMethodObject *pMethodUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ if (!pMethodUNSAFE)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
+ INT32 attributes = 0;
+
+ if (IsNilToken(pMethod->GetMemberDef()))
+ return attributes;
+
+ BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
+ {
+ attributes = (INT32)pMethod->GetImplAttrs();
+ }
+ END_SO_INTOLERANT_CODE;
+
+ return attributes;
+}
+FCIMPLEND
+
+
+FCIMPL1(ReflectClassBaseObject*, RuntimeMethodHandle::GetDeclaringType, MethodDesc *pMethod) {
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(pMethod));
+ }
+ CONTRACTL_END;
+
+ if (!pMethod)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ MethodTable *pMT = pMethod->GetMethodTable();
+ TypeHandle declType(pMT);
+ if (pMT->IsArray())
+ {
+ HELPER_METHOD_FRAME_BEGIN_RET_0();
+
+ // Load the TypeDesc for the array type. Note the returned type is approximate, i.e.
+ // if shared between reference array types then we will get object[] back.
+ DWORD rank = pMT->GetRank();
+ TypeHandle elemType = pMT->GetApproxArrayElementTypeHandle();
+ declType = ClassLoader::LoadArrayTypeThrowing(elemType, pMT->GetInternalCorElementType(), rank);
+ HELPER_METHOD_FRAME_END();
+ }
+ RETURN_CLASS_OBJECT(declType, NULL);
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeMethodHandle::GetSlot, MethodDesc *pMethod) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ if (!pMethod)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ return (INT32)pMethod->GetSlot();
+}
+FCIMPLEND
+
+FCIMPL3(Object *, SignatureNative::GetCustomModifiers, SignatureNative* pSignatureUNSAFE,
+ INT32 parameter, CLR_BOOL fRequired)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ struct
+ {
+ SIGNATURENATIVEREF pSig;
+ PTRARRAYREF retVal;
+ } gc;
+
+ gc.pSig = (SIGNATURENATIVEREF)pSignatureUNSAFE;
+ gc.retVal = NULL;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+ {
+
+ BYTE callConv = *(BYTE*)gc.pSig->GetCorSig();
+ SigTypeContext typeContext;
+ gc.pSig->GetTypeContext(&typeContext);
+ MetaSig sig(gc.pSig->GetCorSig(),
+ gc.pSig->GetCorSigSize(),
+ gc.pSig->GetModule(),
+ &typeContext,
+ (callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_CS_CALLCONV_FIELD ? MetaSig::sigField : MetaSig::sigMember);
+ _ASSERTE(callConv == sig.GetCallingConventionInfo());
+
+ SigPointer argument(NULL, 0);
+
+ PRECONDITION(sig.GetCallingConvention() != IMAGE_CEE_CS_CALLCONV_FIELD || parameter == 1);
+
+ if (parameter == 0)
+ {
+ argument = sig.GetReturnProps();
+ }
+ else
+ {
+ for(INT32 i = 0; i < parameter; i++)
+ sig.NextArg();
+
+ argument = sig.GetArgProps();
+ }
+
+ //if (parameter < 0 || parameter > (INT32)sig.NumFixedArgs())
+ // FCThrowResVoid(kArgumentNullException, W("Arg_ArgumentOutOfRangeException"));
+
+ SigPointer sp = argument;
+ Module* pModule = sig.GetModule();
+ INT32 cMods = 0;
+ CorElementType cmodType;
+
+ CorElementType cmodTypeExpected = fRequired ? ELEMENT_TYPE_CMOD_REQD : ELEMENT_TYPE_CMOD_OPT;
+
+ // Discover the number of required and optional custom modifiers.
+ while(TRUE)
+ {
+ BYTE data;
+ IfFailThrow(sp.GetByte(&data));
+ cmodType = (CorElementType)data;
+
+ if (cmodType == ELEMENT_TYPE_CMOD_REQD || cmodType == ELEMENT_TYPE_CMOD_OPT)
+ {
+ if (cmodType == cmodTypeExpected)
+ {
+ cMods ++;
+ }
+ }
+ else if (cmodType != ELEMENT_TYPE_SENTINEL)
+ {
+ break;
+ }
+
+ IfFailThrow(sp.GetToken(NULL));
+ }
+
+ // Reset sp and populate the arrays for the required and optional custom
+ // modifiers now that we know how long they should be.
+ sp = argument;
+
+ MethodTable *pMT = MscorlibBinder::GetClass(CLASS__TYPE);
+ TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pMT), ELEMENT_TYPE_SZARRAY);
+
+ gc.retVal = (PTRARRAYREF) AllocateArrayEx(arrayHandle, &cMods, 1);
+
+ while(cMods != 0)
+ {
+ BYTE data;
+ IfFailThrow(sp.GetByte(&data));
+ cmodType = (CorElementType)data;
+
+ mdToken token;
+ IfFailThrow(sp.GetToken(&token));
+
+ if (cmodType == cmodTypeExpected)
+ {
+ TypeHandle th = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, token,
+ &typeContext,
+ ClassLoader::ThrowIfNotFound,
+ ClassLoader::FailIfUninstDefOrRef);
+
+ OBJECTREF refType = th.GetManagedClassObject();
+ gc.retVal->SetAt(--cMods, refType);
+ }
+ }
+ }
+ HELPER_METHOD_FRAME_END();
+
+ return OBJECTREFToObject(gc.retVal);
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeMethodHandle::GetMethodDef, ReflectMethodObject *pMethodUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ if (!pMethodUNSAFE)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
+
+ if (pMethod->HasMethodInstantiation())
+ {
+ HELPER_METHOD_FRAME_BEGIN_RET_1(pMethodUNSAFE);
+ {
+ pMethod = pMethod->StripMethodInstantiation();
+ }
+ HELPER_METHOD_FRAME_END();
+ }
+
+ INT32 tkMethodDef = (INT32)pMethod->GetMemberDef();
+ _ASSERTE(TypeFromToken(tkMethodDef) == mdtMethodDef);
+
+ if (IsNilToken(tkMethodDef) || TypeFromToken(tkMethodDef) != mdtMethodDef)
+ return mdMethodDefNil;
+
+ return tkMethodDef;
+}
+FCIMPLEND
+
+FCIMPL6(void, SignatureNative::GetSignature,
+ SignatureNative* pSignatureNativeUNSAFE,
+ PCCOR_SIGNATURE pCorSig, DWORD cCorSig,
+ FieldDesc *pFieldDesc, ReflectMethodObject *pMethodUNSAFE, ReflectClassBaseObject *pDeclaringTypeUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(pDeclaringTypeUNSAFE || pMethodUNSAFE->GetMethod()->IsDynamicMethod());
+ PRECONDITION(CheckPointer(pCorSig, NULL_OK));
+ PRECONDITION(CheckPointer(pMethodUNSAFE, NULL_OK));
+ PRECONDITION(CheckPointer(pFieldDesc, NULL_OK));
+ }
+ CONTRACTL_END;
+
+ struct
+ {
+ REFLECTCLASSBASEREF refDeclaringType;
+ REFLECTMETHODREF refMethod;
+ SIGNATURENATIVEREF pSig;
+ } gc;
+
+ gc.refDeclaringType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
+ gc.refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
+ gc.pSig = (SIGNATURENATIVEREF)pSignatureNativeUNSAFE;
+
+ MethodDesc *pMethod;
+ TypeHandle declType;
+
+ if (gc.refDeclaringType == NULL)
+ {
+ // for dynamic method, see precondition
+ pMethod = gc.refMethod->GetMethod();
+ declType = pMethod->GetMethodTable();
+ }
+ else
+ {
+ pMethod = gc.refMethod != NULL ? gc.refMethod->GetMethod() : NULL;
+ declType = gc.refDeclaringType->GetType();
+ }
+
+ HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
+ {
+ Module* pModule = declType.GetModule();
+
+ if (pMethod)
+ {
+ pMethod->GetSig(&pCorSig, &cCorSig);
+ if (pMethod->GetClassification() == mcInstantiated)
+ {
+ LoaderAllocator *pLoaderAllocator = pMethod->GetLoaderAllocator();
+ if (pLoaderAllocator->IsCollectible())
+ gc.pSig->SetKeepAlive(pLoaderAllocator->GetExposedObject());
+ }
+ }
+ else if (pFieldDesc)
+ pFieldDesc->GetSig(&pCorSig, &cCorSig);
+
+ gc.pSig->m_sig = pCorSig;
+ gc.pSig->m_cSig = cCorSig;
+ gc.pSig->m_pMethod = pMethod;
+
+ REFLECTCLASSBASEREF refDeclType = (REFLECTCLASSBASEREF)declType.GetManagedClassObject();
+ gc.pSig->SetDeclaringType(refDeclType);
+
+ PREFIX_ASSUME(pCorSig!= NULL);
+ BYTE callConv = *(BYTE*)pCorSig;
+ SigTypeContext typeContext;
+ if (pMethod)
+ SigTypeContext::InitTypeContext(
+ pMethod, declType.GetClassOrArrayInstantiation(), pMethod->LoadMethodInstantiation(), &typeContext);
+ else
+ SigTypeContext::InitTypeContext(declType, &typeContext);
+ MetaSig msig(pCorSig, cCorSig, pModule, &typeContext,
+ (callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_CS_CALLCONV_FIELD ? MetaSig::sigField : MetaSig::sigMember);
+
+ if (callConv == IMAGE_CEE_CS_CALLCONV_FIELD)
+ {
+ msig.NextArgNormalized();
+
+ OBJECTREF refRetType = msig.GetLastTypeHandleThrowing().GetManagedClassObject();
+ gc.pSig->SetReturnType(refRetType);
+ }
+ else
+ {
+ gc.pSig->SetCallingConvention(msig.GetCallingConventionInfo());
+
+ OBJECTREF refRetType = msig.GetRetTypeHandleThrowing().GetManagedClassObject();
+ gc.pSig->SetReturnType(refRetType);
+
+ INT32 nArgs = msig.NumFixedArgs();
+ TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pRuntimeTypeClass), ELEMENT_TYPE_SZARRAY);
+
+ PTRARRAYREF ptrArrayarguments = (PTRARRAYREF) AllocateArrayEx(arrayHandle, &nArgs, 1);
+ gc.pSig->SetArgumentArray(ptrArrayarguments);
+
+ for (INT32 i = 0; i < nArgs; i++)
+ {
+ msig.NextArg();
+
+ OBJECTREF refArgType = msig.GetLastTypeHandleThrowing().GetManagedClassObject();
+ gc.pSig->SetArgument(i, refArgType);
+ }
+
+ _ASSERTE(gc.pSig->m_returnType != NULL);
+ }
+ }
+ HELPER_METHOD_FRAME_END();
+}
+FCIMPLEND
+
+FCIMPL2(FC_BOOL_RET, SignatureNative::CompareSig, SignatureNative* pLhsUNSAFE, SignatureNative* pRhsUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ INT32 ret = 0;
+
+ struct
+ {
+ SIGNATURENATIVEREF pLhs;
+ SIGNATURENATIVEREF pRhs;
+ } gc;
+
+ gc.pLhs = (SIGNATURENATIVEREF)pLhsUNSAFE;
+ gc.pRhs = (SIGNATURENATIVEREF)pRhsUNSAFE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+ {
+ ret = MetaSig::CompareMethodSigs(
+ gc.pLhs->GetCorSig(), gc.pLhs->GetCorSigSize(), gc.pLhs->GetModule(), NULL,
+ gc.pRhs->GetCorSig(), gc.pRhs->GetCorSigSize(), gc.pRhs->GetModule(), NULL);
+ }
+ HELPER_METHOD_FRAME_END();
+ FC_RETURN_BOOL(ret);
+}
+FCIMPLEND
+
+void QCALLTYPE RuntimeMethodHandle::GetMethodInstantiation(MethodDesc * pMethod, QCall::ObjectHandleOnStack retTypes, BOOL fAsRuntimeTypeArray)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ Instantiation inst = pMethod->LoadMethodInstantiation();
+
+ GCX_COOP();
+ retTypes.Set(CopyRuntimeTypeHandles(NULL, inst.GetRawArgs(), inst.GetNumArgs(), fAsRuntimeTypeArray ? CLASS__CLASS : CLASS__TYPE));
+ END_QCALL;
+
+ return;
+}
+
+FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::HasMethodInstantiation, MethodDesc * pMethod)
+{
+ FCALL_CONTRACT;
+
+ FC_RETURN_BOOL(pMethod->HasMethodInstantiation());
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsGenericMethodDefinition, MethodDesc * pMethod)
+{
+ FCALL_CONTRACT;
+
+ FC_RETURN_BOOL(pMethod->IsGenericMethodDefinition());
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsDynamicMethod, MethodDesc * pMethod)
+{
+ FCALL_CONTRACT;
+
+ FC_RETURN_BOOL(pMethod->IsNoMetadata());
+}
+FCIMPLEND
+
+FCIMPL1(Object*, RuntimeMethodHandle::GetResolver, MethodDesc * pMethod)
+{
+ FCALL_CONTRACT;
+
+ if (!pMethod)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ OBJECTREF resolver = NULL;
+ if (pMethod->IsLCGMethod())
+ {
+ resolver = pMethod->AsDynamicMethodDesc()->GetLCGMethodResolver()->GetManagedResolver();
+ }
+ return OBJECTREFToObject(resolver);
+}
+FCIMPLEND
+
+void QCALLTYPE RuntimeMethodHandle::Destroy(MethodDesc * pMethod)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ if (pMethod == NULL)
+ COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
+
+ DynamicMethodDesc* pDynamicMethodDesc = pMethod->AsDynamicMethodDesc();
+
+ GCX_COOP();
+
+ // Destroy should be called only if the managed part is gone.
+ _ASSERTE(OBJECTREFToObject(pDynamicMethodDesc->GetLCGMethodResolver()->GetManagedResolver()) == NULL);
+
+ // Fire Unload Dynamic Method Event here
+ ETW::MethodLog::DynamicMethodDestroyed(pMethod);
+
+ pDynamicMethodDesc->Destroy();
+
+ END_QCALL;
+ }
+
+FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsTypicalMethodDefinition, ReflectMethodObject *pMethodUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ if (!pMethodUNSAFE)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
+
+ FC_RETURN_BOOL(pMethod->IsTypicalMethodDefinition());
+}
+FCIMPLEND
+
+void QCALLTYPE RuntimeMethodHandle::GetTypicalMethodDefinition(MethodDesc * pMethod, QCall::ObjectHandleOnStack refMethod)
+ {
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+#ifdef _DEBUG
+ {
+ GCX_COOP();
+ _ASSERTE(((ReflectMethodObject *)(*refMethod.m_ppObject))->GetMethod() == pMethod);
+ }
+#endif
+ MethodDesc *pMethodTypical = pMethod->LoadTypicalMethodDefinition();
+ if (pMethodTypical != pMethod)
+ {
+ GCX_COOP();
+ refMethod.Set(pMethodTypical->GetStubMethodInfo());
+ }
+ END_QCALL;
+
+ return;
+}
+
+void QCALLTYPE RuntimeMethodHandle::StripMethodInstantiation(MethodDesc * pMethod, QCall::ObjectHandleOnStack refMethod)
+ {
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+
+ if (!pMethod)
+ COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
+
+#ifdef _DEBUG
+ {
+ GCX_COOP();
+ _ASSERTE(((ReflectMethodObject *)(*refMethod.m_ppObject))->GetMethod() == pMethod);
+ }
+#endif
+ MethodDesc *pMethodStripped = pMethod->StripMethodInstantiation();
+ if (pMethodStripped != pMethod)
+ {
+ GCX_COOP();
+ refMethod.Set(pMethodStripped->GetStubMethodInfo());
+ }
+ END_QCALL;
+
+ return;
+}
+
+// In the VM there might be more than one MethodDescs for a "method"
+// examples are methods on generic types which may have additional instantiating stubs
+// and methods on value types which may have additional unboxing stubs.
+//
+// For generic methods we always hand out an instantiating stub except for a generic method definition
+// For non-generic methods on generic types we need an instantiating stub if it's one of the following
+// - static method on a generic class
+// - static or instance method on a generic interface
+// - static or instance method on a generic value type
+// The Reflection policy is to always hand out instantiating stubs in these cases
+//
+// For methods on non-generic value types we can use either the cannonical method or the unboxing stub
+// The Reflection policy is to always hand out unboxing stubs if the methods are virtual methods
+// The reason for this is that in the current implementation of the class loader, the v-table slots for
+// those methods point to unboxing stubs already. Note that this is just a implementation choice
+// that might change in the future. But we should always keep this Reflection policy an invariant.
+//
+// For virtual methods on generic value types (intersection of the two cases), reflection will hand
+// out an unboxing instantiating stub
+//
+// GetInstantiatingStub is called to:
+// 1. create an InstantiatedMethodDesc for a generic method when calling BindGenericArguments() on a generic
+// method. In this case instArray will not be null.
+// 2. create an InstantiatedMethodDesc for a method in a generic class. In this case instArray will be null.
+// 3. create an UnboxingStub for a method in a value type. In this case instArray will be null.
+// For case 2 and 3, an instantiating stub or unboxing stub might not be needed in which case the original
+// MethodDesc is returned.
+FCIMPL3(MethodDesc*, RuntimeMethodHandle::GetStubIfNeeded,
+ MethodDesc *pMethod,
+ ReflectClassBaseObject *pTypeUNSAFE,
+ PtrArray* instArrayUNSAFE)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+ PTRARRAYREF instArray = (PTRARRAYREF)ObjectToOBJECTREF(instArrayUNSAFE);
+
+ if (refType == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle instType = refType->GetType();
+ MethodDesc *pNewMethod = pMethod;
+
+ // error conditions
+ if (!pMethod)
+ FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
+
+ if (instType.IsNull())
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ // Perf optimization: this logic is actually duplicated in FindOrCreateAssociatedMethodDescForReflection, but since it
+ // is the more common case it's worth the duplicate check here to avoid the helper method frame
+ if ( instArray == NULL &&
+ ( pMethod->HasMethodInstantiation() ||
+ ( !instType.IsValueType() &&
+ ( !instType.HasInstantiation() || instType.IsGenericTypeDefinition() ) ) ) )
+ {
+ return pNewMethod;
+ }
+
+ HELPER_METHOD_FRAME_BEGIN_RET_2(refType, instArray);
+ {
+ TypeHandle *inst = NULL;
+ DWORD ntypars = 0;
+
+ if (instArray != NULL)
+ {
+ ntypars = instArray->GetNumComponents();
+
+ size_t size = ntypars * sizeof(TypeHandle);
+ if ((size / sizeof(TypeHandle)) != ntypars) // uint over/underflow
+ COMPlusThrow(kArgumentException);
+ inst = (TypeHandle*) _alloca(size);
+
+ for (DWORD i = 0; i < ntypars; i++)
+ {
+ REFLECTCLASSBASEREF instRef = (REFLECTCLASSBASEREF)instArray->GetAt(i);
+
+ if (instRef == NULL)
+ COMPlusThrowArgumentNull(W("inst"), W("ArgumentNull_ArrayElement"));
+
+ inst[i] = instRef->GetType();
+ }
+ }
+
+ pNewMethod = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMethod, instType, Instantiation(inst, ntypars));
+ }
+ HELPER_METHOD_FRAME_END();
+
+ return pNewMethod;
+}
+FCIMPLEND
+
+
+FCIMPL2(MethodDesc*, RuntimeMethodHandle::GetMethodFromCanonical, MethodDesc *pMethod, ReflectClassBaseObject *pTypeUNSAFE)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(pMethod));
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
+
+ TypeHandle instType = refType->GetType();
+ MethodDesc* pMDescInCanonMT = instType.GetMethodTable()->GetParallelMethodDesc(pMethod);
+
+ return pMDescInCanonMT;
+}
+FCIMPLEND
+
+
+FCIMPL2(MethodBody *, RuntimeMethodHandle::GetMethodBody, ReflectMethodObject *pMethodUNSAFE, ReflectClassBaseObject *pDeclaringTypeUNSAFE)
+{
+ CONTRACTL
+ {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ struct _gc
+ {
+ METHODBODYREF MethodBodyObj;
+ EXCEPTIONHANDLINGCLAUSEREF EHClauseObj;
+ LOCALVARIABLEINFOREF LocalVariableInfoObj;
+ U1ARRAYREF U1Array;
+ BASEARRAYREF TempArray;
+ REFLECTCLASSBASEREF declaringType;
+ REFLECTMETHODREF refMethod;
+ } gc;
+
+ gc.MethodBodyObj = NULL;
+ gc.EHClauseObj = NULL;
+ gc.LocalVariableInfoObj = NULL;
+ gc.U1Array = NULL;
+ gc.TempArray = NULL;
+ gc.declaringType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
+ gc.refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
+
+
+ if (!gc.refMethod)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ MethodDesc* pMethod = gc.refMethod->GetMethod();
+
+ TypeHandle declaringType = gc.declaringType == NULL ? TypeHandle() : gc.declaringType->GetType();
+
+ if (!pMethod->IsIL())
+ return NULL;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+ {
+ MethodDesc *pMethodIL = pMethod;
+ if (pMethod->IsWrapperStub())
+ pMethodIL = pMethod->GetWrappedMethodDesc();
+
+ COR_ILMETHOD* pILHeader = pMethodIL->GetILHeader();
+
+ if (pILHeader)
+ {
+ MethodTable * pExceptionHandlingClauseMT = MscorlibBinder::GetClass(CLASS__EH_CLAUSE);
+ TypeHandle thEHClauseArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pExceptionHandlingClauseMT), ELEMENT_TYPE_SZARRAY);
+
+ MethodTable * pLocalVariableMT = MscorlibBinder::GetClass(CLASS__LOCAL_VARIABLE_INFO);
+ TypeHandle thLocalVariableArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pLocalVariableMT), ELEMENT_TYPE_SZARRAY);
+
+ Module* pModule = pMethod->GetModule();
+ COR_ILMETHOD_DECODER::DecoderStatus status;
+ COR_ILMETHOD_DECODER header(pILHeader, pModule->GetMDImport(), &status);
+
+ if (status != COR_ILMETHOD_DECODER::SUCCESS)
+ {
+ if (status == COR_ILMETHOD_DECODER::VERIFICATION_ERROR)
+ {
+ // Throw a verification HR
+ COMPlusThrowHR(COR_E_VERIFICATION);
+ }
+ else
+ {
+ COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
+ }
+ }
+
+ gc.MethodBodyObj = (METHODBODYREF)AllocateObject(MscorlibBinder::GetClass(CLASS__METHOD_BODY));
+
+ gc.MethodBodyObj->m_maxStackSize = header.GetMaxStack();
+ gc.MethodBodyObj->m_initLocals = !!(header.GetFlags() & CorILMethod_InitLocals);
+
+ if (header.IsFat())
+ gc.MethodBodyObj->m_localVarSigToken = header.GetLocalVarSigTok();
+ else
+ gc.MethodBodyObj->m_localVarSigToken = 0;
+
+ // Allocate the array of IL and fill it in from the method header.
+ BYTE* pIL = const_cast<BYTE*>(header.Code);
+ COUNT_T cIL = header.GetCodeSize();
+ gc.U1Array = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, cIL);
+
+ SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_IL, gc.U1Array, GetAppDomain());
+ memcpyNoGCRefs(gc.MethodBodyObj->m_IL->GetDataPtr(), pIL, cIL);
+
+ // Allocate the array of exception clauses.
+ INT32 cEh = (INT32)header.EHCount();
+ const COR_ILMETHOD_SECT_EH* ehInfo = header.EH;
+ gc.TempArray = (BASEARRAYREF) AllocateArrayEx(thEHClauseArray, &cEh, 1);
+
+ SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_exceptionClauses, gc.TempArray, GetAppDomain());
+
+ for (INT32 i = 0; i < cEh; i++)
+ {
+ COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff;
+ const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehClause =
+ (const COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)ehInfo->EHClause(i, &ehBuff);
+
+ gc.EHClauseObj = (EXCEPTIONHANDLINGCLAUSEREF) AllocateObject(pExceptionHandlingClauseMT);
+
+ gc.EHClauseObj->m_flags = ehClause->GetFlags();
+ gc.EHClauseObj->m_tryOffset = ehClause->GetTryOffset();
+ gc.EHClauseObj->m_tryLength = ehClause->GetTryLength();
+ gc.EHClauseObj->m_handlerOffset = ehClause->GetHandlerOffset();
+ gc.EHClauseObj->m_handlerLength = ehClause->GetHandlerLength();
+
+ if ((ehClause->GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER) == 0)
+ gc.EHClauseObj->m_catchToken = ehClause->GetClassToken();
+ else
+ gc.EHClauseObj->m_filterOffset = ehClause->GetFilterOffset();
+
+ gc.MethodBodyObj->m_exceptionClauses->SetAt(i, (OBJECTREF) gc.EHClauseObj);
+ SetObjectReference((OBJECTREF*)&(gc.EHClauseObj->m_methodBody), (OBJECTREF)gc.MethodBodyObj, GetAppDomain());
+ }
+
+ if (header.LocalVarSig != NULL)
+ {
+ SigTypeContext sigTypeContext(pMethod, declaringType, pMethod->LoadMethodInstantiation());
+ MetaSig metaSig(header.LocalVarSig,
+ header.cbLocalVarSig,
+ pModule,
+ &sigTypeContext,
+ MetaSig::sigLocalVars);
+ INT32 cLocals = metaSig.NumFixedArgs();
+ gc.TempArray = (BASEARRAYREF) AllocateArrayEx(thLocalVariableArray, &cLocals, 1);
+ SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_localVariables, gc.TempArray, GetAppDomain());
+
+ for (INT32 i = 0; i < cLocals; i ++)
+ {
+ gc.LocalVariableInfoObj = (LOCALVARIABLEINFOREF)AllocateObject(pLocalVariableMT);
+
+ gc.LocalVariableInfoObj->m_localIndex = i;
+
+ metaSig.NextArg();
+
+ CorElementType eType;
+ IfFailThrow(metaSig.GetArgProps().PeekElemType(&eType));
+ if (ELEMENT_TYPE_PINNED == eType)
+ gc.LocalVariableInfoObj->m_bIsPinned = TRUE;
+
+ TypeHandle tempType= metaSig.GetArgProps().GetTypeHandleThrowing(pModule, &sigTypeContext);
+ OBJECTREF refLocalType = tempType.GetManagedClassObject();
+ gc.LocalVariableInfoObj->SetType(refLocalType);
+ gc.MethodBodyObj->m_localVariables->SetAt(i, (OBJECTREF) gc.LocalVariableInfoObj);
+ }
+ }
+ else
+ {
+ INT32 cLocals = 0;
+ gc.TempArray = (BASEARRAYREF) AllocateArrayEx(thLocalVariableArray, &cLocals, 1);
+ SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_localVariables, gc.TempArray, GetAppDomain());
+ }
+ }
+ }
+ HELPER_METHOD_FRAME_END();
+
+ return (MethodBody*)OBJECTREFToObject(gc.MethodBodyObj);
+}
+FCIMPLEND
+
+FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsConstructor, MethodDesc *pMethod)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(pMethod));
+ }
+ CONTRACTL_END;
+
+ BOOL ret = FALSE;
+ BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
+ ret = (BOOL)pMethod->IsClassConstructorOrCtor();
+ END_SO_INTOLERANT_CODE;
+ FC_RETURN_BOOL(ret);
+}
+FCIMPLEND
+
+FCIMPL1(Object*, RuntimeMethodHandle::GetLoaderAllocator, MethodDesc *pMethod)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ OBJECTREF loaderAllocator = NULL;
+
+ if (!pMethod)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(loaderAllocator);
+
+ LoaderAllocator *pLoaderAllocator = pMethod->GetLoaderAllocator();
+ loaderAllocator = pLoaderAllocator->GetExposedObject();
+
+ HELPER_METHOD_FRAME_END();
+
+ return OBJECTREFToObject(loaderAllocator);
+}
+FCIMPLEND
+
+//*********************************************************************************************
+//*********************************************************************************************
+//*********************************************************************************************
+
+FCIMPL1(StringObject*, RuntimeFieldHandle::GetName, ReflectFieldObject *pFieldUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTFIELDREF refField = (REFLECTFIELDREF)ObjectToOBJECTREF(pFieldUNSAFE);
+ if (!refField)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ FieldDesc *pField = refField->GetField();
+
+ STRINGREF refString = NULL;
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refField);
+ {
+ refString = StringObject::NewString(pField->GetName());
+ }
+ HELPER_METHOD_FRAME_END();
+ return (StringObject*)OBJECTREFToObject(refString);
+}
+FCIMPLEND
+
+FCIMPL1(LPCUTF8, RuntimeFieldHandle::GetUtf8Name, FieldDesc *pField) {
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(pField));
+ }
+ CONTRACTL_END;
+
+ LPCUTF8 szFieldName;
+
+ if (FAILED(pField->GetName_NoThrow(&szFieldName)))
+ {
+ FCThrow(kBadImageFormatException);
+ }
+ return szFieldName;
+}
+FCIMPLEND
+
+FCIMPL2(FC_BOOL_RET, RuntimeFieldHandle::MatchesNameHash, FieldDesc * pField, ULONG hash)
+{
+ FCALL_CONTRACT;
+
+ FC_RETURN_BOOL(pField->MightHaveName(hash));
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeFieldHandle::GetAttributes, FieldDesc *pField) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ if (!pField)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ INT32 ret = 0;
+ BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
+ ret = (INT32)pField->GetAttributes();
+ END_SO_INTOLERANT_CODE;
+ return ret;
+}
+FCIMPLEND
+
+FCIMPL1(ReflectClassBaseObject*, RuntimeFieldHandle::GetApproxDeclaringType, FieldDesc *pField) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ if (!pField)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle th = TypeHandle(pField->GetApproxEnclosingMethodTable()); // <REVISIT_TODO> this needs to be checked - see bug 184355 </REVISIT_TODO>
+ RETURN_CLASS_OBJECT(th, NULL);
+}
+FCIMPLEND
+
+FCIMPL1(INT32, RuntimeFieldHandle::GetToken, ReflectFieldObject *pFieldUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTFIELDREF refField = (REFLECTFIELDREF)ObjectToOBJECTREF(pFieldUNSAFE);
+ if (!refField)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ FieldDesc *pField = refField->GetField();
+
+ INT32 tkFieldDef = (INT32)pField->GetMemberDef();
+ _ASSERTE(!IsNilToken(tkFieldDef) || tkFieldDef == mdFieldDefNil);
+ return tkFieldDef;
+}
+FCIMPLEND
+
+FCIMPL2(FieldDesc*, RuntimeFieldHandle::GetStaticFieldForGenericType, FieldDesc *pField, ReflectClassBaseObject *pDeclaringTypeUNSAFE)
+{
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTCLASSBASEREF refDeclaringType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
+
+ if ((refDeclaringType == NULL) || (pField == NULL))
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ TypeHandle declaringType = refDeclaringType->GetType();
+
+ if (!pField)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+ if (declaringType.IsTypeDesc())
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+ MethodTable *pMT = declaringType.AsMethodTable();
+
+ _ASSERTE(pField->IsStatic());
+ if (pMT->HasGenericsStaticsInfo())
+ pField = pMT->GetFieldDescByIndex(pField->GetApproxEnclosingMethodTable()->GetIndexForFieldDesc(pField));
+ _ASSERTE(!pField->IsSharedByGenericInstantiations());
+ _ASSERTE(pField->GetEnclosingMethodTable() == pMT);
+
+ return pField;
+}
+FCIMPLEND
+
+FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBaseObject* pAssemblyUNSAFE) {
+ FCALL_CONTRACT;
+
+ ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
+
+ if (refAssembly == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
+ Assembly* currentAssembly = pAssembly->GetCurrentAssembly();
+
+ if (currentAssembly == NULL)
+ return NULL;
+
+ Module *pModule = currentAssembly->GetManifestModule();
+ DomainFile * pDomainFile = pModule->FindDomainFile(GetAppDomain());
+
+#ifdef _DEBUG
+ OBJECTREF orModule;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refAssembly);
+ orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
+ if (orModule == NULL)
+ orModule = pModule->GetExposedObject();
+#else
+ OBJECTREF orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
+ if (orModule != NULL)
+ return (ReflectModuleBaseObject*)OBJECTREFToObject(orModule);
+
+ HELPER_METHOD_FRAME_BEGIN_RET_1(refAssembly);
+ orModule = pModule->GetExposedObject();
+#endif
+
+ HELPER_METHOD_FRAME_END();
+ return (ReflectModuleBaseObject*)OBJECTREFToObject(orModule);
+
+}
+FCIMPLEND
+
+FCIMPL1(INT32, AssemblyHandle::GetToken, AssemblyBaseObject* pAssemblyUNSAFE) {
+ FCALL_CONTRACT;
+
+ ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
+
+ if (refAssembly == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
+ mdAssembly token = mdAssemblyNil;
+
+ IMDInternalImport *mdImport = pAssembly->GetCurrentAssembly()->GetManifestImport();
+
+ if (mdImport != 0)
+ {
+ if (FAILED(mdImport->GetAssemblyFromScope(&token)))
+ {
+ FCThrow(kBadImageFormatException);
+ }
+ }
+
+ return token;
+}
+FCIMPLEND
+
+#ifdef FEATURE_APTCA
+FCIMPL2(FC_BOOL_RET, AssemblyHandle::AptcaCheck, AssemblyBaseObject* pTargetAssemblyUNSAFE, AssemblyBaseObject* pSourceAssemblyUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ ASSEMBLYREF refTargetAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pTargetAssemblyUNSAFE);
+ ASSEMBLYREF refSourceAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pSourceAssemblyUNSAFE);
+
+ if ((refTargetAssembly == NULL) || (refSourceAssembly == NULL))
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ DomainAssembly *pTargetAssembly = refTargetAssembly->GetDomainAssembly();
+ DomainAssembly *pSourceAssembly = refSourceAssembly->GetDomainAssembly();
+
+ if (pTargetAssembly == pSourceAssembly)
+ FC_RETURN_BOOL(TRUE);
+
+ BOOL bResult = TRUE;
+
+ HELPER_METHOD_FRAME_BEGIN_RET_2(refSourceAssembly, refTargetAssembly);
+ {
+ bResult = ( pTargetAssembly->GetAssembly()->AllowUntrustedCaller() || // target assembly allows untrusted callers unconditionally
+ pSourceAssembly->GetSecurityDescriptor()->IsFullyTrusted());
+ }
+ HELPER_METHOD_FRAME_END();
+
+ FC_RETURN_BOOL(bResult);
+}
+FCIMPLEND
+#endif // FEATURE_APTCA
+
+void QCALLTYPE ModuleHandle::GetPEKind(QCall::ModuleHandle pModule, DWORD* pdwPEKind, DWORD* pdwMachine)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ pModule->GetFile()->GetPEKindAndMachine(pdwPEKind, pdwMachine);
+ END_QCALL;
+}
+
+FCIMPL1(INT32, ModuleHandle::GetMDStreamVersion, ReflectModuleBaseObject * pModuleUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
+
+ if (refModule == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ Module *pModule = refModule->GetModule();
+
+ if (pModule->IsResource())
+ return 0;
+
+ return pModule->GetMDImport()->GetMetadataStreamVersion();
+}
+FCIMPLEND
+
+void QCALLTYPE ModuleHandle::GetModuleType(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle globalTypeHandle = TypeHandle();
+
+ BEGIN_QCALL;
+
+ EX_TRY
+ {
+ globalTypeHandle = TypeHandle(pModule->GetGlobalMethodTable());
+ }
+ EX_SWALLOW_NONTRANSIENT;
+
+ if (!globalTypeHandle.IsNull())
+ {
+ GCX_COOP();
+ retType.Set(globalTypeHandle.GetManagedClassObject());
+ }
+
+ END_QCALL;
+
+ return;
+}
+
+FCIMPL1(INT32, ModuleHandle::GetToken, ReflectModuleBaseObject * pModuleUNSAFE) {
+ CONTRACTL {
+ FCALL_CHECK;
+ }
+ CONTRACTL_END;
+
+ REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
+
+ if (refModule == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ Module *pModule = refModule->GetModule();
+
+ if (pModule->IsResource())
+ return mdModuleNil;
+
+ return pModule->GetMDImport()->GetModuleFromScope();
+}
+FCIMPLEND
+
+FCIMPL1(IMDInternalImport*, ModuleHandle::GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE)
+{
+ FCALL_CONTRACT;
+
+ REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
+
+ if (refModule == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ Module *pModule = refModule->GetModule();
+
+ if (pModule->IsResource())
+ return NULL;
+
+ return pModule->GetMDImport();
+}
+FCIMPLEND
+
+BOOL QCALLTYPE ModuleHandle::ContainsPropertyMatchingHash(QCall::ModuleHandle pModule, INT32 tkProperty, ULONG hash)
+{
+ QCALL_CONTRACT;
+
+ BOOL fContains = TRUE;
+
+ BEGIN_QCALL;
+
+ fContains = pModule->MightContainMatchingProperty(tkProperty, hash);
+
+ END_QCALL;
+
+ return fContains;
+}
+
+void QCALLTYPE ModuleHandle::ResolveType(QCall::ModuleHandle pModule, INT32 tkType, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ TypeHandle typeHandle;
+
+ BEGIN_QCALL;
+
+ _ASSERTE(!IsNilToken(tkType));
+
+ SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
+ typeHandle = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, tkType, &typeContext,
+ ClassLoader::ThrowIfNotFound,
+ ClassLoader::PermitUninstDefOrRef);
+
+ GCX_COOP();
+ retType.Set(typeHandle.GetManagedClassObject());
+
+ END_QCALL;
+
+ return;
+}
+
+MethodDesc *QCALLTYPE ModuleHandle::ResolveMethod(QCall::ModuleHandle pModule, INT32 tkMemberRef, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount)
+{
+ QCALL_CONTRACT;
+
+ MethodDesc* pMD = NULL;
+
+ BEGIN_QCALL;
+
+ _ASSERTE(!IsNilToken(tkMemberRef));
+
+ BOOL strictMetadataChecks = (TypeFromToken(tkMemberRef) == mdtMethodSpec);
+
+ SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
+ pMD = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(pModule, tkMemberRef, &typeContext, strictMetadataChecks, FALSE);
+
+ // This will get us the instantiating or unboxing stub if needed
+ pMD = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMD, pMD->GetMethodTable(), pMD->GetMethodInstantiation());
+
+ END_QCALL;
+
+ return pMD;
+}
+
+void QCALLTYPE ModuleHandle::ResolveField(QCall::ModuleHandle pModule, INT32 tkMemberRef, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount, QCall::ObjectHandleOnStack retField)
+{
+ QCALL_CONTRACT;
+
+ FieldDesc* pField = NULL;
+
+ BEGIN_QCALL;
+
+ _ASSERTE(!IsNilToken(tkMemberRef));
+
+ SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
+ pField = MemberLoader::GetFieldDescFromMemberDefOrRef(pModule, tkMemberRef, &typeContext, FALSE);
+ GCX_COOP();
+ retField.Set(pField->GetStubFieldInfo());
+
+ END_QCALL;
+
+ return;
+}
+
+void QCALLTYPE ModuleHandle::GetAssembly(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retAssembly)
+{
+ QCALL_CONTRACT;
+
+ DomainAssembly *pAssembly = NULL;
+
+ BEGIN_QCALL;
+ pAssembly = pModule->GetDomainAssembly();
+
+ GCX_COOP();
+ retAssembly.Set(pAssembly->GetExposedAssemblyObject());
+ END_QCALL;
+
+ return;
+}
+
+FCIMPL5(ReflectMethodObject*, ModuleHandle::GetDynamicMethod, ReflectMethodObject *pMethodUNSAFE, ReflectModuleBaseObject *pModuleUNSAFE, StringObject *name, U1Array *sig, Object *resolver) {
+ CONTRACTL {
+ FCALL_CHECK;
+ PRECONDITION(CheckPointer(name));
+ PRECONDITION(CheckPointer(sig));
+ }
+ CONTRACTL_END;
+
+ DynamicMethodDesc *pNewMD = NULL;
+
+ struct
+ {
+ STRINGREF nameRef;
+ OBJECTREF resolverRef;
+ OBJECTREF methodRef;
+ REFLECTMETHODREF retMethod;
+ REFLECTMODULEBASEREF refModule;
+ } gc;
+ gc.nameRef = (STRINGREF)name;
+ gc.resolverRef = (OBJECTREF)resolver;
+ gc.methodRef = ObjectToOBJECTREF(pMethodUNSAFE);
+ gc.retMethod = NULL;
+ gc.refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
+
+ if (gc.refModule == NULL)
+ FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
+
+ Module *pModule = gc.refModule->GetModule();
+
+ HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
+
+ DomainFile *pDomainModule = pModule->GetDomainFile();
+
+ U1ARRAYREF dataArray = (U1ARRAYREF)sig;
+ DWORD sigSize = dataArray->GetNumComponents();
+ NewHolder<BYTE> pSig(new BYTE[sigSize]);
+ memcpy(pSig, dataArray->GetDataPtr(), sigSize);
+
+ DWORD length = gc.nameRef->GetStringLength();
+ NewArrayHolder<char> pName(new char[(length + 1) * 2]);
+ pName[0] = '\0';
+ length = WszWideCharToMultiByte(CP_UTF8, 0, gc.nameRef->GetBuffer(), length, pName, (length + 1) * 2 - sizeof(char), NULL, NULL);
+ if (length)
+ pName[length / sizeof(char)] = '\0';
+
+ DynamicMethodTable *pMTForDynamicMethods = pDomainModule->GetDynamicMethodTable();
+ pNewMD = pMTForDynamicMethods->GetDynamicMethod(pSig, sigSize, pName);
+ _ASSERTE(pNewMD != NULL);
+ // pNewMD now owns pSig and pName.
+ pSig.SuppressRelease();
+ pName.SuppressRelease();
+
+ // create a handle to hold the resolver objectref
+ OBJECTHANDLE resolverHandle = pDomainModule->GetAppDomain()->CreateLongWeakHandle(gc.resolverRef);
+ pNewMD->GetLCGMethodResolver()->SetManagedResolver(resolverHandle);
+ gc.retMethod = pNewMD->GetStubMethodInfo();
+ gc.retMethod->SetKeepAlive(gc.resolverRef);
+
+ LoaderAllocator *pLoaderAllocator = pModule->GetLoaderAllocator();
+
+ if (pLoaderAllocator->IsCollectible())
+ pLoaderAllocator->AddReference();
+
+ HELPER_METHOD_FRAME_END();
+
+ return (ReflectMethodObject*)OBJECTREFToObject(gc.retMethod);
+}
+FCIMPLEND
+
+void QCALLTYPE RuntimeMethodHandle::GetCallerType(QCall::StackCrawlMarkHandle pStackMark, QCall::ObjectHandleOnStack retType)
+{
+ QCALL_CONTRACT;
+
+ BEGIN_QCALL;
+ GCX_COOP();
+ MethodTable *pMT = NULL;
+
+ pMT = SystemDomain::GetCallersType(pStackMark);
+
+ if (pMT != NULL)
+ retType.Set(pMT->GetManagedClassObject());
+
+ END_QCALL;
+
+ return;
+}