예제 #1
0
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;
}
예제 #2
0
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();
}
예제 #3
0
//+----------------------------------------------------------------------------
//
//  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);
}