HRESULT CorHost::UnloadDomain(IUnknown *pUnkDomain) { HRESULT hr = S_OK; if(!pUnkDomain) return E_POINTER; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); Thread* pThread = GetThread(); if (!pThread) IfFailGo(E_UNEXPECTED); IfFailGo(QuickCOMStartup()); BEGIN_ENSURE_COOPERATIVE_GC(); COMPLUS_TRY { // unload doesn't need to switch to the domain to be unloaded OBJECTREF pRef = NULL; GCPROTECT_BEGIN(pRef); pRef = GetObjectRefFromComIP(pUnkDomain); MethodDesc* pMD = g_Mscorlib.GetMethod(METHOD__APP_DOMAIN__UNLOAD); ARG_SLOT arg = ObjToArgSlot((OBJECTREF) pRef); pMD->Call(&arg, METHOD__APP_DOMAIN__UNLOAD); GCPROTECT_END(); } COMPLUS_CATCH { hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH END_ENSURE_COOPERATIVE_GC(); ErrExit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return hr; }
TypeHandle Binder::LookupType(BinderTypeID id, BOOL fLoad) { _ASSERTE(m_pModule != NULL); _ASSERTE(id != TYPE__NIL); _ASSERTE(id <= m_cTypeHandles); THROWSCOMPLUSEXCEPTION(); TypeHandle th; const TypeDescription *d = m_typeDescriptions + id - 1; OBJECTREF pThrowable = NULL; GCPROTECT_BEGIN(pThrowable); NameHandle nh(d->type, TypeHandle(GetClass(d->classID)), d->rank); if (!fLoad) nh.SetTokenNotToLoad(tdAllTypes); th = m_pModule->GetClassLoader()->FindTypeHandle(&nh, &pThrowable); GCPROTECT_END(); if (th.IsNull()) { if (fLoad) COMPlusThrow(pThrowable); return TypeHandle(); } m_pTypeHandles[id-1] = th; return th; }
void Binder::InitClass(MethodTable *pMT) { THROWSCOMPLUSEXCEPTION(); OBJECTREF throwable = NULL; GCPROTECT_BEGIN(throwable); if (!pMT->CheckRunClassInit(&throwable)) COMPlusThrow(throwable); GCPROTECT_END(); }
MethodTable *Binder::LookupClass(BinderClassID id, BOOL fLoad) { _ASSERTE(m_pModule != NULL); _ASSERTE(id != CLASS__NIL); _ASSERTE(id <= m_cClassRIDs); MethodTable *pMT; const ClassDescription *d = m_classDescriptions + id - 1; NameHandle nh(d->name); if (!fLoad) { nh.SetTokenNotToLoad(tdAllTypes); pMT = m_pModule->GetClassLoader()->FindTypeHandle(&nh).AsMethodTable(); if (pMT == NULL) return NULL; } else { THROWSCOMPLUSEXCEPTION(); BEGIN_ENSURE_COOPERATIVE_GC(); OBJECTREF pThrowable = NULL; GCPROTECT_BEGIN(pThrowable); pMT = m_pModule->GetClassLoader()->FindTypeHandle(&nh, &pThrowable).AsMethodTable(); if (pMT == NULL) { _ASSERTE(!"EE expects class to exist"); COMPlusThrow(pThrowable); } GCPROTECT_END(); END_ENSURE_COOPERATIVE_GC(); } _ASSERTE(pMT->GetModule() == m_pModule); mdTypeDef td = pMT->GetClass()->GetCl(); _ASSERTE(!IsNilToken(td)); _ASSERTE(RidFromToken(td) <= USHRT_MAX); m_pClassRIDs[id-1] = (USHORT) RidFromToken(td); m_pModule->StoreTypeDef(td, pMT); return pMT; }
static IUnknown* GetDomainsExposedObjectWorker(Thread* pThread, AppDomain* pDomain) { HRESULT hr = S_OK; IUnknown* punk = NULL; OBJECTREF ref = NULL; GCPROTECT_BEGIN(ref); DECLARE_ALLOCA_CONTEXT_TRANSITION_FRAME(pFrame); // ok to do this here as we are just grabbing a wrapper. No managed code will run pThread->EnterContextRestricted(pDomain->GetDefaultContext(), pFrame, TRUE); ref = pDomain->GetExposedObject(); IfFailThrow(QuickCOMStartup()); punk = GetComIPFromObjectRef(&ref); pThread->ReturnToContext(pFrame, TRUE); GCPROTECT_END(); return punk; }
HRESULT CorHost::CreateEvidence(IUnknown **pEvidence) { HRESULT hr = S_OK; if (!pEvidence) return E_POINTER; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); // Create the domain. Thread* pThread = GetThread(); if (!pThread) IfFailGo(E_UNEXPECTED); IfFailGo(QuickCOMStartup()); BOOL fWasGCEnabled; fWasGCEnabled = !pThread->PreemptiveGCDisabled(); if (fWasGCEnabled) pThread->DisablePreemptiveGC(); COMPLUS_TRY { struct _gc { OBJECTREF pEvidence; } gc; ZeroMemory(&gc, sizeof(gc)); MethodTable* pMT = g_Mscorlib.GetClass(CLASS__EVIDENCE); GCPROTECT_BEGIN(gc); gc.pEvidence = AllocateObject(pMT); IfFailThrow(QuickCOMStartup()); *pEvidence = GetComIPFromObjectRef((OBJECTREF*) &gc.pEvidence); GCPROTECT_END(); } COMPLUS_CATCH { hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH if (fWasGCEnabled) pThread->EnablePreemptiveGC(); ErrExit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return hr; }
HRESULT AssemblySpec::CheckFileAccess(LPCWSTR wszFile,DWORD dwAccess) { BOOL bRes=FALSE; BEGIN_ENSURE_COOPERATIVE_GC(); STRINGREF sFileName=NULL; GCPROTECT_BEGIN(sFileName); sFileName = COMString::NewString(wszFile); ARG_SLOT args[]={ ObjToArgSlot(sFileName), dwAccess, }; bRes = Security::CheckFileAccess(args); GCPROTECT_END(); END_ENSURE_COOPERATIVE_GC(); return bRes ? S_OK : HRESULT_FROM_WIN32(E_ACCESSDENIED); };
HRESULT CorHost::CreateDomainSetup(IUnknown **pAppDomainSetup) { HRESULT hr = S_OK; if (!pAppDomainSetup) return E_POINTER; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); // Create the domain. Thread* pThread = GetThread(); if (!pThread) IfFailGo(E_UNEXPECTED); IfFailGo(QuickCOMStartup()); BEGIN_ENSURE_COOPERATIVE_GC(); COMPLUS_TRY { struct _gc { OBJECTREF pSetup; } gc; ZeroMemory(&gc, sizeof(gc)); MethodTable* pMT = g_Mscorlib.GetClass(CLASS__APPDOMAIN_SETUP); GCPROTECT_BEGIN(gc); gc.pSetup = AllocateObject(pMT); IfFailThrow(QuickCOMStartup()); *pAppDomainSetup = GetComIPFromObjectRef((OBJECTREF*) &gc.pSetup); GCPROTECT_END(); } COMPLUS_CATCH { hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH END_ENSURE_COOPERATIVE_GC(); ErrExit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return hr; }
Object * FinalizerThread::DoOneFinalization(Object* fobj, Thread* pThread,int bitToCheck,bool *pbTerminate) { STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_COOPERATIVE; bool fTerminate=false; Object *pReturnObject = NULL; AppDomain* targetAppDomain = fobj->GetAppDomain(); AppDomain* currentDomain = pThread->GetDomain(); if (! targetAppDomain || ! targetAppDomain->CanThreadEnter(pThread)) { // if can't get into domain to finalize it, then it must be agile so finalize in current domain targetAppDomain = currentDomain; #if CHECK_APP_DOMAIN_LEAKS { // object must be agile if can't get into it's domain if (g_pConfig->AppDomainLeaks() && !fobj->TrySetAppDomainAgile(FALSE)) _ASSERTE(!"Found non-agile GC object which should have been finalized during app domain unload."); } #endif } if (targetAppDomain == currentDomain) { if (!targetAppDomain->IsRudeUnload() || fobj->GetMethodTable()->HasCriticalFinalizer()) { class ResetFinalizerStartTime { public: ResetFinalizerStartTime() { if (CLRHosted()) { g_ObjFinalizeStartTime = CLRGetTickCount64(); } } ~ResetFinalizerStartTime() { if (g_ObjFinalizeStartTime) { g_ObjFinalizeStartTime = 0; } } }; { ThreadLocaleHolder localeHolder; { ResetFinalizerStartTime resetTime; CallFinalizer(fobj); } } pThread->InternalReset(FALSE); } } else { if (! targetAppDomain->GetDefaultContext()) { // Can no longer enter domain becuase the handle containing the context has been // destroyed so just bail. Should only get this if are at the stage of nuking the // handles in the domain if it's still open. _ASSERTE(targetAppDomain->IsUnloading() && targetAppDomain->ShouldHaveFinalization()); } else if (!currentDomain->IsDefaultDomain()) { // this means we are in some other domain, so need to return back out through the DoADCallback // and handle the object from there in another domain. pReturnObject = fobj; fTerminate = true; } else { // otherwise call back to ourselves to process as many as we can in that other domain FinalizeAllObjects_Args args; args.fobj = ObjectToOBJECTREF(fobj); args.bitToCheck = bitToCheck; GCPROTECT_BEGIN(args.fobj); { ThreadLocaleHolder localeHolder; _ASSERTE(pThreadTurnAround != NULL); ManagedThreadBase::FinalizerAppDomain(targetAppDomain, FinalizeAllObjects_Wrapper, &args, pThreadTurnAround); } pThread->InternalReset(FALSE); // process the object we got back or be done if we got back null pReturnObject = OBJECTREFToObject(args.fobj); GCPROTECT_END(); } } *pbTerminate = fTerminate; return pReturnObject; }
CustomMarshalerInfo::CustomMarshalerInfo(BaseDomain *pDomain, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes) : m_NativeSize(0) , m_hndManagedType(hndManagedType) , m_hndCustomMarshaler(NULL) , m_pMarshalNativeToManagedMD(NULL) , m_pMarshalManagedToNativeMD(NULL) , m_pCleanUpNativeDataMD(NULL) , m_pCleanUpManagedDataMD(NULL) , m_bDataIsByValue(FALSE) { CONTRACTL { THROWS; GC_TRIGGERS; MODE_COOPERATIVE; PRECONDITION(CheckPointer(pDomain)); } CONTRACTL_END; // Make sure the custom marshaller implements ICustomMarshaler. if (!hndCustomMarshalerType.GetMethodTable()->CanCastToNonVariantInterface(MscorlibBinder::GetClass(CLASS__ICUSTOM_MARSHALER))) { DefineFullyQualifiedNameForClassW() COMPlusThrow(kApplicationException, IDS_EE_ICUSTOMMARSHALERNOTIMPL, GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable())); } // Determine if this type is a value class. m_bDataIsByValue = m_hndManagedType.GetMethodTable()->IsValueType(); // Custom marshalling of value classes is not currently supported. if (m_bDataIsByValue) COMPlusThrow(kNotSupportedException, W("NotSupported_ValueClassCM")); #ifndef CROSSGEN_COMPILE // Run the <clinit> on the marshaler since it might not have run yet. hndCustomMarshalerType.GetMethodTable()->EnsureInstanceActive(); hndCustomMarshalerType.GetMethodTable()->CheckRunClassInitThrowing(); // Create a COM+ string that will contain the string cookie. STRINGREF CookieStringObj = StringObject::NewString(strCookie, cCookieStrBytes); GCPROTECT_BEGIN(CookieStringObj); #endif // Load the method desc's for all the methods in the ICustomMarshaler interface. m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, hndCustomMarshalerType); m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, hndCustomMarshalerType); m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, hndCustomMarshalerType); m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, hndCustomMarshalerType); // Load the method desc for the static method to retrieve the instance. MethodDesc *pGetCustomMarshalerMD = GetCustomMarshalerMD(CustomMarshalerMethods_GetInstance, hndCustomMarshalerType); // If the GetInstance method is generic, get an instantiating stub for it - // the CallDescr infrastructure doesn't know how to pass secret generic arguments. if (pGetCustomMarshalerMD->RequiresInstMethodTableArg()) { pGetCustomMarshalerMD = MethodDesc::FindOrCreateAssociatedMethodDesc( pGetCustomMarshalerMD, hndCustomMarshalerType.GetMethodTable(), FALSE, // forceBoxedEntryPoint Instantiation(), // methodInst FALSE, // allowInstParam FALSE); // forceRemotableMethod _ASSERTE(!pGetCustomMarshalerMD->RequiresInstMethodTableArg()); } #ifndef CROSSGEN_COMPILE MethodDescCallSite getCustomMarshaler(pGetCustomMarshalerMD, (OBJECTREF*)&CookieStringObj); pGetCustomMarshalerMD->EnsureActive(); // Prepare the arguments that will be passed to GetCustomMarshaler. ARG_SLOT GetCustomMarshalerArgs[] = { ObjToArgSlot(CookieStringObj) }; // Call the GetCustomMarshaler method to retrieve the custom marshaler to use. OBJECTREF CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs); if (!CustomMarshalerObj) { DefineFullyQualifiedNameForClassW() COMPlusThrow(kApplicationException, IDS_EE_NOCUSTOMMARSHALER, GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable())); } m_hndCustomMarshaler = pDomain->CreateHandle(CustomMarshalerObj); // Retrieve the size of the native data. if (m_bDataIsByValue) { // <TODO>@TODO(DM): Call GetNativeDataSize() to retrieve the size of the native data.</TODO> _ASSERTE(!"Value classes are not yet supported by the custom marshaler!"); } else { m_NativeSize = sizeof(void *); } GCPROTECT_END(); #endif }
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(); }
HRESULT STDMETHODCALLTYPE ICorDBPrivHelperImpl::CreateManagedObject( /*in*/ WCHAR *wszAssemblyName, /*in*/ WCHAR *wszModuleName, /*in*/ mdTypeDef classToken, /*in*/ void *rawData, /*out*/ IUnknown **ppUnk) { _ASSERTE(TypeFromToken((mdTypeDef)classToken) == mdtTypeDef); _ASSERTE(wszAssemblyName && wszModuleName && ppUnk); if (!wszAssemblyName || !wszModuleName || classToken == mdTokenNil) return E_INVALIDARG; if (!ppUnk) return E_POINTER; HRESULT hr = S_OK; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); // This will set up a managed thread object if one does not already exist // for this particular thread. Thread* pThread = SetupThread(); if (pThread == NULL) { hr = E_OUTOFMEMORY; goto Exit; } // Start up COM Interop if (FAILED(hr = QuickCOMStartup())) goto Exit; { // Don't want to be interrupted... BOOL fWasGCEnabled = !pThread->PreemptiveGCDisabled(); if (fWasGCEnabled) pThread->DisablePreemptiveGC(); Assembly *pAssembly; Module *pModule; if (GetAppDomain() == NULL) hr = E_INVALIDARG; else { // Try and load the assembly, given the name provided. OBJECTREF pThrowable = NULL; GCPROTECT_BEGIN(pThrowable); hr = AssemblySpec::LoadAssembly(wszAssemblyName, &pAssembly, &pThrowable); GCPROTECT_END(); if (SUCCEEDED(hr)) { _ASSERTE(pAssembly); // Try and load the module, given the name provided. hr = pAssembly->GetModuleFromFilename(wszModuleName, &pModule); if (SUCCEEDED(hr)) { _ASSERTE(pModule); // If the class isn't known,then don't try and create it. if (!pModule->GetMDImport()->IsValidToken(classToken)) hr = E_INVALIDARG; else { COMPLUS_TRY { OBJECTREF obj = NULL; GCPROTECT_BEGIN(obj); // Now try and get the TypeHandle for the given token NameHandle nameHandle(pModule, classToken); TypeHandle typeHandle = pAssembly->LoadTypeHandle(&nameHandle, &obj); // If an exception was thrown at some point, convert // it to an HRESULT if (obj != NULL) hr = SecurityHelper::MapToHR(obj); // No longer need the object, can be GC'd if desired obj = NULL; if (SUCCEEDED(hr)) { _ASSERTE(typeHandle.AsMethodTable()); MethodTable *pMT = typeHandle.AsMethodTable(); if (!pMT->GetClass()->IsValueClass() || pMT->ContainsPointers()) hr = CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS; if (SUCCEEDED(hr)) { // Now run the class initialiser if (!pMT->CheckRunClassInit(&obj)) hr = SecurityHelper::MapToHR(obj); // No longer need the object, can be GC'd if // desired obj = NULL; if (SUCCEEDED(hr)) { // If successful, allocate an instance of // the class // This may throw an // OutOfMemoryException, but the below // COMPLUS_CATCH should handle it. If // the class is a ValueClass, the // created object will be a boxed // ValueClass. obj = AllocateObject(pMT); // Now create a COM wrapper around // this object. Note that this can // also throw. *ppUnk = GetComIPFromObjectRef(&obj); _ASSERTE(ppUnk); // This is the nasty part. We're gonna // copy the raw data we're given over // the new instance of the value // class... CopyValueClass(obj->UnBox(), rawData, pMT, obj->GetAppDomain()); // No longer need the object, can be GC'd // if desired obj = NULL; } } } GCPROTECT_END(); // obj } COMPLUS_CATCH { // If there's an exception, convert it to an HR hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH } } } } if (fWasGCEnabled) pThread->EnablePreemptiveGC(); } Exit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return (hr); }
// Creates a domain in the runtime. The identity array is // a pointer to an array TYPE containing IIdentity objects defining // the security identity. HRESULT CorHost::CreateDomainEx(LPCWSTR pwzFriendlyName, IUnknown* pSetup, // Optional IUnknown* pEvidence, // Optional IUnknown ** pAppDomain) { HRESULT hr = S_OK; if(!pwzFriendlyName) return E_POINTER; if(pAppDomain == NULL) return E_POINTER; if(g_RefCount == 0) return E_FAIL; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); // This will set up a managed thread object if one does not already exist // for this particular thread. Thread* pThread = SetupThread(); if (pThread == NULL) { hr = E_OUTOFMEMORY; goto Exit; } if (!pThread) { hr = E_UNEXPECTED; goto Exit; } if (FAILED(hr = QuickCOMStartup())) goto Exit; BOOL fWasGCEnabled; fWasGCEnabled = !pThread->PreemptiveGCDisabled(); if (fWasGCEnabled) pThread->DisablePreemptiveGC(); COMPLUS_TRY { struct _gc { STRINGREF pName; OBJECTREF pSetup; OBJECTREF pEvidence; APPDOMAINREF pDomain; } gc; ZeroMemory(&gc, sizeof(gc)); GCPROTECT_BEGIN(gc); gc.pName = COMString::NewString(pwzFriendlyName); if(pSetup) gc.pSetup = GetObjectRefFromComIP(pSetup); if(pEvidence) gc.pEvidence = GetObjectRefFromComIP(pEvidence); MethodDesc *pMD = g_Mscorlib.GetMethod(METHOD__APP_DOMAIN__CREATE_DOMAIN); ARG_SLOT args[3] = { ObjToArgSlot(gc.pName), ObjToArgSlot(gc.pEvidence), ObjToArgSlot(gc.pSetup), }; gc.pDomain = (APPDOMAINREF) ArgSlotToObj(pMD->Call(args, METHOD__APP_DOMAIN__CREATE_DOMAIN)); IfFailThrow(QuickCOMStartup()); *pAppDomain = GetComIPFromObjectRef((OBJECTREF*) &gc.pDomain); GCPROTECT_END(); } COMPLUS_CATCH { hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH if (fWasGCEnabled) pThread->EnablePreemptiveGC(); Exit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return hr; }
HRESULT STDMETHODCALLTYPE ICorDBPrivHelperImpl::GetManagedObjectContents( /* in */ IUnknown *pObject, /* in */ void *rawData, /* in */ ULONG32 dataSize) { if (!pObject || !rawData) return E_POINTER; if (dataSize == 0) return E_INVALIDARG; HRESULT hr = S_OK; BEGINCANNOTTHROWCOMPLUSEXCEPTION(); // This will set up a managed thread object if one does not already exist // for this particular thread. Thread* pThread = SetupThread(); if (pThread == NULL) { hr = E_OUTOFMEMORY; goto Exit; } { // Don't want to be interrupted... BOOL fWasGCEnabled = !pThread->PreemptiveGCDisabled(); if (fWasGCEnabled) pThread->DisablePreemptiveGC(); OBJECTREF obj = NULL; GCPROTECT_BEGIN(obj); COMPLUS_TRY { // Get the Object out of the IUnknown. obj = GetObjectRefFromComIP(pObject); MethodTable *pMT = obj->GetMethodTable(); if (!pMT->GetClass()->IsValueClass() || pMT->ContainsPointers() || (pMT->GetClass()->GetNumInstanceFieldBytes() != dataSize)) hr = CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS; // This is the nasty part. We're gonna copy the raw data out // of the object and pass it out. if (SUCCEEDED(hr)) { memcpy(rawData, obj->UnBox(), dataSize); } } COMPLUS_CATCH { // If there's an exception, convert it to an HR hr = SecurityHelper::MapToHR(GETTHROWABLE()); } COMPLUS_END_CATCH obj = NULL; GCPROTECT_END(); // obj if (fWasGCEnabled) pThread->EnablePreemptiveGC(); } Exit: ENDCANNOTTHROWCOMPLUSEXCEPTION(); return (hr); }
//+---------------------------------------------------------------------------- // // 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); }