static MethodDesc* GetInvokeMemberMD() { static MethodDesc* s_pInvokeMemberMD = NULL; // If we already have retrieved the specified MD then just return it. if (s_pInvokeMemberMD == NULL) { // The method desc has not been retrieved yet so find it. MethodDesc *pMD = g_Mscorlib.GetMethod(METHOD__CLASS__INVOKE_MEMBER); // Ensure that the value types in the signature are loaded. MetaSig::EnsureSigValueTypesLoaded(pMD->GetSig(), pMD->GetModule()); // Cache the method desc. s_pInvokeMemberMD = pMD; } // Return the specified method desc. return s_pInvokeMemberMD; }
VOID ComCallWrapper::InvokeByNameCallback(LPVOID ptr) { InvokeByNameArgs* args = (InvokeByNameArgs*)ptr; INT32 NumByrefArgs = 0; INT32 *aByrefArgMngVariantIndex = NULL; INT32 iArg; struct __gc { OBJECTREF Target; STRINGREF MemberName; PTRARRAYREF ParamArray; OBJECTREF TmpObj; OBJECTREF RetVal; } gc; ZeroMemory(&gc, sizeof(gc)); GCPROTECT_BEGIN(gc); gc.MemberName = COMString::NewString(args->MemberName); gc.ParamArray = (PTRARRAYREF)AllocateObjectArray(args->ArgCount, g_pObjectClass); // // Fill in the arguments. // for (iArg = 0; iArg < args->ArgCount; iArg++) { // Convert the variant. VARIANT *pSrcOleVariant = &args->ArgList[iArg]; OleVariant::MarshalObjectForOleVariant(pSrcOleVariant, &gc.TmpObj); gc.ParamArray->SetAt(iArg, gc.TmpObj); // If the argument is byref then add it to the array of byref arguments. if (V_VT(pSrcOleVariant) & VT_BYREF) { if (aByrefArgMngVariantIndex == NULL) { aByrefArgMngVariantIndex = (INT32 *)_alloca(sizeof(INT32) * args->ArgCount); } aByrefArgMngVariantIndex[NumByrefArgs] = iArg; NumByrefArgs++; } } gc.Target = ObjectFromHandle(args->pThis->m_hThis); // // Invoke using IReflect::InvokeMember // EEClass *pClass = gc.Target->GetClass(); // Retrieve the method descriptor that will be called on. MethodDesc *pMD = GetInvokeMemberMD(); // Prepare the arguments that will be passed to Invoke. ARG_SLOT Args[] = { ObjToArgSlot(GetReflectionObject(pClass)), // IReflect ObjToArgSlot(gc.MemberName), // name (ARG_SLOT) args->BindingFlags, // invokeAttr ObjToArgSlot(GetOleAutBinder()),// binder ObjToArgSlot(gc.Target), // target ObjToArgSlot(gc.ParamArray), // args ObjToArgSlot(NULL), // modifiers ObjToArgSlot(NULL), // culture ObjToArgSlot(NULL) // namedParameters }; // Do the actual method invocation. MetaSig metaSig(pMD->GetSig(),pMD->GetModule()); gc.RetVal = ArgSlotToObj(pMD->Call(Args, &metaSig)); // // Convert the return value and the byref arguments. // // Convert all the ByRef arguments back. for (iArg = 0; iArg < NumByrefArgs; iArg++) { INT32 i = aByrefArgMngVariantIndex[iArg]; gc.TmpObj = gc.ParamArray->GetAt(i); OleVariant::MarshalOleRefVariantForObject(&gc.TmpObj, &args->ArgList[i]); } // Convert the return COM+ object to an OLE variant. if (args->pRetVal) OleVariant::MarshalOleVariantForObject(&gc.RetVal, args->pRetVal); GCPROTECT_END(); }
//+---------------------------------------------------------------------------- // // Method: CStackBuilderSink::PrivateProcessMessage, public // // Synopsis: Builds the stack and calls an object // //+---------------------------------------------------------------------------- FCIMPL7(Object*, CStackBuilderSink::PrivateProcessMessage, Object* pSBSinkUNSAFE, ReflectBaseObject* pMethodBaseUNSAFE, PTRArray* pArgsUNSAFE, Object* pServerUNSAFE, void* iMethodPtr, BOOL fContext, PTRARRAYREF* ppVarOutParams) { OBJECTREF ret = NULL; struct _gc { REFLECTBASEREF pMethodBase; PTRARRAYREF pArgs; OBJECTREF pServer; OBJECTREF pSBSink; } gc; gc.pMethodBase = (REFLECTBASEREF) pMethodBaseUNSAFE; gc.pArgs = (PTRARRAYREF) pArgsUNSAFE; gc.pServer = (OBJECTREF) pServerUNSAFE; gc.pSBSink = (OBJECTREF) pSBSinkUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_NOPOLL(Frame::FRAME_ATTR_RETURNOBJ); GCPROTECT_BEGIN(gc); HELPER_METHOD_POLL(); //-[autocvtpro]------------------------------------------------------- THROWSCOMPLUSEXCEPTION(); TRIGGERSGC(); LOG((LF_REMOTING, LL_INFO10, "CStackBuilderSink::PrivateProcessMessage\n")); _ASSERTE(gc.pMethodBase != NULL); ReflectMethod *pRM = (ReflectMethod *)gc.pMethodBase->GetData(); MethodDesc *pMD = pRM->pMethod; // Either pServer is non-null or the method is static (but not both) _ASSERTE((gc.pServer!=NULL) == !(pMD->IsStatic())); // Check if this is an interface invoke, if yes, then we have to find the // real method descriptor on the class of the server object. if(pMD->GetMethodTable()->IsInterface()) { _ASSERTE(gc.pServer != NULL); MethodDesc* pTemp = pMD; // NOTE: This method can trigger GC pMD = gc.pServer->GetMethodTable()->GetMethodDescForInterfaceMethod(pMD, gc.pServer); if(NULL == pMD) { MAKE_WIDEPTR_FROMUTF8(wName, pTemp->GetName()) COMPlusThrow(kMissingMethodException, IDS_EE_MISSING_METHOD, NULL, wName); } } MetaSig mSig(pMD->GetSig(), pMD->GetModule()); // get the target depending on whether the method is virtual or non-virtual // like a constructor, private or final method const BYTE* pTarget = NULL; if (iMethodPtr) { pTarget = (const BYTE*) iMethodPtr; } else { // Get the address of the code pTarget = MethodTable::GetTargetFromMethodDescAndServer(pMD, &(gc.pServer), fContext); } VASigCookie *pCookie = NULL; _ASSERTE(NULL != pTarget); GCPROTECT_BEGIN (ret); // this function does the work ::CallDescrWithObjectArray( gc.pServer, pRM, pTarget, &mSig, pCookie, gc.pServer==NULL?TRUE:FALSE, //fIsStatic gc.pArgs, &ret, ppVarOutParams); GCPROTECT_END (); LOG((LF_REMOTING, LL_INFO10, "CStackBuilderSink::PrivateProcessMessage OUT\n")); //-[autocvtepi]------------------------------------------------------- GCPROTECT_END(); HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(ret); }