FCIMPLEND // Return a method info for the method were the exception was thrown FCIMPL1(ReflectMethodObject*, SystemNative::GetMethodFromStackTrace, ArrayBase* pStackTraceUNSAFE) { FCALL_CONTRACT; I1ARRAYREF pArray(static_cast<I1Array *>(pStackTraceUNSAFE)); StackTraceArray stackArray(pArray); if (!stackArray.Size()) return NULL; // The managed stacktrace classes always returns typical method definition, so we don't need to bother providing exact instantiation. // Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation(pElements[0].pFunc, pElements[0].pExactGenericArgsToken, pTypeHandle, &pMD); MethodDesc* pFunc = stackArray[0].pFunc; // Strip the instantiation to make sure that the reflection never gets a bad method desc back. REFLECTMETHODREF refRet = NULL; HELPER_METHOD_FRAME_BEGIN_RET_0() pFunc = pFunc->LoadTypicalMethodDefinition(); refRet = pFunc->GetStubMethodInfo(); _ASSERTE(pFunc->IsRuntimeMethodHandle()); HELPER_METHOD_FRAME_END(); return (ReflectMethodObject*)OBJECTREFToObject(refRet); }
FCIMPLEND FCIMPL1(Object*, AssemblyNameNative::ToString, Object* refThisUNSAFE) { FCALL_CONTRACT; OBJECTREF pObj = NULL; ASSEMBLYNAMEREF pThis = (ASSEMBLYNAMEREF) (OBJECTREF) refThisUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_1(pThis); if (pThis == NULL) COMPlusThrow(kNullReferenceException, W("NullReference_This")); Thread *pThread = GetThread(); CheckPointHolder cph(pThread->m_MarshalAlloc.GetCheckpoint()); //hold checkpoint for autorelease AssemblySpec spec; spec.InitializeSpec(&(pThread->m_MarshalAlloc), (ASSEMBLYNAMEREF*) &pThis, FALSE, FALSE); StackSString name; #ifndef FEATURE_FUSION spec.GetFileOrDisplayName(ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE | ASM_DISPLAYF_PUBLIC_KEY_TOKEN, name); #else spec.GetFileOrDisplayName(0, name); #endif // FEATURE_FUSION pObj = (OBJECTREF) StringObject::NewString(name); HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(pObj); }
FCIMPLEND FCIMPL0(StringObject*, SystemNative::GetRuntimeDirectory) { FCALL_CONTRACT; STRINGREF refRetVal = NULL; DWORD dwFile = MAX_LONGPATH+1; HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal); SString wszFilePathString; WCHAR * wszFile = wszFilePathString.OpenUnicodeBuffer(dwFile); HRESULT hr = GetInternalSystemDirectory(wszFile, &dwFile); wszFilePathString.CloseBuffer(dwFile); if(FAILED(hr)) COMPlusThrowHR(hr); dwFile--; // remove the trailing NULL if(dwFile) refRetVal = StringObject::NewString(wszFile, dwFile); HELPER_METHOD_FRAME_END(); return (StringObject*)OBJECTREFToObject(refRetVal); }
FCIMPLEND FCIMPL0(StringObject*, SystemNative::_GetModuleFileName) { FCALL_CONTRACT; STRINGREF refRetVal = NULL; HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal); if (g_pCachedModuleFileName) { refRetVal = StringObject::NewString(g_pCachedModuleFileName); } else { SString wszFilePathString; WCHAR * wszFile = wszFilePathString.OpenUnicodeBuffer(MAX_LONGPATH); DWORD lgth = WszGetModuleFileName(NULL, wszFile, MAX_LONGPATH); if (!lgth) { COMPlusThrowWin32(); } wszFilePathString.CloseBuffer(lgth); refRetVal = StringObject::NewString(wszFilePathString.GetUnicode()); } HELPER_METHOD_FRAME_END(); return (StringObject*)OBJECTREFToObject(refRetVal); }
FCIMPL0(Object*, SystemNative::GetCommandLineArgs) { FCALL_CONTRACT; PTRARRAYREF strArray = NULL; HELPER_METHOD_FRAME_BEGIN_RET_1(strArray); LPWSTR commandLine; commandLine = WszGetCommandLine(); if (commandLine==NULL) COMPlusThrowOM(); DWORD numArgs = 0; LPWSTR* argv = SegmentCommandLine(commandLine, &numArgs); if (!argv) COMPlusThrowOM(); _ASSERTE(numArgs > 0); strArray = (PTRARRAYREF) AllocateObjectArray(numArgs, g_pStringClass); // Copy each argument into new Strings. for(unsigned int i=0; i<numArgs; i++) { STRINGREF str = StringObject::NewString(argv[i]); STRINGREF * destData = ((STRINGREF*)(strArray->GetDataPtr())) + i; SetObjectReference((OBJECTREF*)destData, (OBJECTREF)str, strArray->GetAppDomain()); } delete [] argv; HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(strArray); }
FCIMPLEND // Note: Arguments checked in IL. FCIMPL1(Object*, SystemNative::_GetEnvironmentVariable, StringObject* strVarUNSAFE) { FCALL_CONTRACT; STRINGREF refRetVal; STRINGREF strVar; refRetVal = NULL; strVar = ObjectToSTRINGREF(strVarUNSAFE); HELPER_METHOD_FRAME_BEGIN_RET_2(refRetVal, strVar); int len; // Get the length of the environment variable. PathString envPath; // prefix complains if pass a null ptr in, so rely on the final length parm instead len = WszGetEnvironmentVariable(strVar->GetBuffer(), envPath); if (len != 0) { // Allocate the string. refRetVal = StringObject::NewString(len); wcscpy_s(refRetVal->GetBuffer(), len + 1, envPath); } HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(refRetVal); }
FCIMPL1(Object*, AssemblyNameNative::GetFileInformation, StringObject* filenameUNSAFE) { FCALL_CONTRACT; struct _gc { ASSEMBLYNAMEREF result; STRINGREF filename; } gc; gc.result = NULL; gc.filename = (STRINGREF) filenameUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc); if (gc.filename == NULL) COMPlusThrow(kArgumentNullException, W("ArgumentNull_FileName")); if (gc.filename->GetStringLength() == 0) COMPlusThrow(kArgumentException, W("Argument_EmptyFileName")); gc.result = (ASSEMBLYNAMEREF) AllocateObject(MscorlibBinder::GetClass(CLASS__ASSEMBLY_NAME)); /////////////////////////////////////////////// SString sFileName(gc.filename->GetBuffer()); PEImageHolder pImage = PEImage::OpenImage(sFileName, MDInternalImport_NoCache); EX_TRY { #ifdef FEATURE_CORECLR // Allow AssemblyLoadContext.GetAssemblyName for native images on CoreCLR if (pImage->HasNTHeaders() && pImage->HasCorHeader() && pImage->HasNativeHeader()) pImage->VerifyIsNIAssembly(); else pImage->VerifyIsAssembly(); #else pImage->VerifyIsAssembly(); #endif } EX_CATCH { Exception *ex = GET_EXCEPTION(); EEFileLoadException::Throw(sFileName,ex->GetHR(),ex); } EX_END_CATCH_UNREACHABLE; SString sUrl = sFileName; PEAssembly::PathToUrl(sUrl); AssemblySpec spec; spec.InitializeSpec(TokenFromRid(mdtAssembly,1),pImage->GetMDImport(),NULL,TRUE); spec.SetCodeBase(sUrl); spec.AssemblyNameInit(&gc.result, pImage); HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(gc.result); }
void FinalizerThread::FinalizeAllObjects_Wrapper(void *ptr) { STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_TRIGGERS; STATIC_CONTRACT_MODE_COOPERATIVE; FinalizeAllObjects_Args *args = (FinalizeAllObjects_Args *) ptr; _ASSERTE(args->fobj); Object *fobj = OBJECTREFToObject(args->fobj); args->fobj = NULL; // don't want to do this guy again, if we take an exception here: args->fobj = ObjectToOBJECTREF(FinalizeAllObjects(fobj, args->bitToCheck)); }
FCIMPLEND // Note: Arguments checked in IL. FCIMPL1(Object*, SystemNative::_GetEnvironmentVariable, StringObject* strVarUNSAFE) { FCALL_CONTRACT; STRINGREF refRetVal; STRINGREF strVar; refRetVal = NULL; strVar = ObjectToSTRINGREF(strVarUNSAFE); HELPER_METHOD_FRAME_BEGIN_RET_2(refRetVal, strVar); // We loop round getting the length of the env var and then trying to copy // the value into a managed string. Usually we'll go through this loop // precisely once, but the caution is ncessary in case the variable mutates // beneath us. int len, newLen; // Get the length of the environment variable. WCHAR dummy; // prefix complains if pass a null ptr in, so rely on the final length parm instead len = WszGetEnvironmentVariable(strVar->GetBuffer(), &dummy, 0); while (len != 0) { // Allocate the string. refRetVal = StringObject::NewString(len); // Get the value. newLen = WszGetEnvironmentVariable(strVar->GetBuffer(), refRetVal->GetBuffer(), len); if (newLen != (len - 1)) { // The envvar changed, need to do this again. Let GC collect the // string we just allocated. refRetVal = NULL; // Go back and try again. len = newLen; } else break; } HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(refRetVal); }
FCIMPLEND #ifndef FEATURE_CORECLR FCIMPL1(Object*, AssemblyNameNative::EscapeCodeBase, StringObject* filenameUNSAFE) { FCALL_CONTRACT; STRINGREF rv = NULL; STRINGREF filename = (STRINGREF) filenameUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_1(filename); LPWSTR pCodeBase = NULL; DWORD dwCodeBase = 0; CQuickBytes qb; if (filename != NULL) { WCHAR* pString; int iString; filename->RefInterpretGetStringValuesDangerousForGC(&pString, &iString); dwCodeBase = (DWORD) iString; pCodeBase = (LPWSTR) qb.AllocThrows((++dwCodeBase) * sizeof(WCHAR)); memcpy(pCodeBase, pString, dwCodeBase*sizeof(WCHAR)); } if(pCodeBase) { CQuickBytes qb2; DWORD dwEscaped = 1; DWORD flags = 0; if (RunningOnWin7()) flags |= URL_ESCAPE_AS_UTF8; UrlEscape(pCodeBase, (LPWSTR) qb2.Ptr(), &dwEscaped, flags); LPWSTR result = (LPWSTR)qb2.AllocThrows((++dwEscaped) * sizeof(WCHAR)); HRESULT hr = UrlEscape(pCodeBase, result, &dwEscaped, flags); if (SUCCEEDED(hr)) rv = StringObject::NewString(result); else COMPlusThrowHR(hr); } HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(rv); }
FCIMPLEND FCIMPL1(Object*, AssemblyNameNative::GetPublicKeyToken, Object* refThisUNSAFE) { FCALL_CONTRACT; OBJECTREF orOutputArray = NULL; OBJECTREF refThis = (OBJECTREF) refThisUNSAFE; HELPER_METHOD_FRAME_BEGIN_RET_1(refThis); if (refThis == NULL) COMPlusThrow(kNullReferenceException, W("NullReference_This")); ASSEMBLYNAMEREF orThis = (ASSEMBLYNAMEREF)refThis; U1ARRAYREF orPublicKey = orThis->GetPublicKey(); if (orPublicKey != NULL) { DWORD cb = orPublicKey->GetNumComponents(); StrongNameBufferHolder<BYTE> pbToken; if (cb) { CQuickBytes qb; BYTE *pbKey = (BYTE*) qb.AllocThrows(cb); memcpy(pbKey, orPublicKey->GetDataPtr(), cb); { GCX_PREEMP(); if (!StrongNameTokenFromPublicKey(pbKey, cb, &pbToken, &cb)) COMPlusThrowHR(StrongNameErrorInfo()); } } Security::CopyEncodingToByteArray(pbToken, cb, &orOutputArray); } HELPER_METHOD_FRAME_END(); return OBJECTREFToObject(orOutputArray); }
FCIMPLEND FCIMPL0(StringObject*, SystemNative::GetDeveloperPath) { #ifdef FEATURE_FUSION FCALL_CONTRACT; STRINGREF refDevPath = NULL; LPWSTR pPath = NULL; DWORD lgth = 0; HELPER_METHOD_FRAME_BEGIN_RET_1(refDevPath); SystemDomain::System()->GetDevpathW(&pPath, &lgth); if(lgth) refDevPath = StringObject::NewString(pPath, lgth); HELPER_METHOD_FRAME_END(); return (StringObject*)OBJECTREFToObject(refDevPath); #else return NULL; #endif }
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; }
FCIMPLEND // array is GC protected by caller void ArrayInitializeWorker(ARRAYBASEREF * arrayRef, MethodTable* pArrayMT, MethodTable* pElemMT) { STATIC_CONTRACT_MODE_COOPERATIVE; STATIC_CONTRACT_SO_INTOLERANT; // Ensure that the array element type is fully loaded before executing its code pElemMT->EnsureInstanceActive(); //can not use contract here because of SEH _ASSERTE(IsProtectedByGCFrame (arrayRef)); SIZE_T offset = ArrayBase::GetDataPtrOffset(pArrayMT); SIZE_T size = pArrayMT->GetComponentSize(); SIZE_T cElements = (*arrayRef)->GetNumComponents(); MethodTable * pCanonMT = pElemMT->GetCanonicalMethodTable(); WORD slot = pCanonMT->GetDefaultConstructorSlot(); PCODE ctorFtn = pCanonMT->GetSlot(slot); #ifdef _X86_ BEGIN_CALL_TO_MANAGED(); typedef void (__fastcall * CtorFtnType)(BYTE*, BYTE*); for (SIZE_T i = 0; i < cElements; i++) { // Since GetSlot() is not idempotent and may have returned // a non-optimal entry-point the first time round. if (i == 1) { ctorFtn = pCanonMT->GetSlot(slot); } BYTE* thisPtr = (((BYTE*) OBJECTREFToObject (*arrayRef)) + offset); #ifdef _DEBUG __asm { mov ECX, thisPtr mov EDX, pElemMT // Instantiation argument if the type is generic call [ctorFtn] nop // Mark the fact that we can call managed code } #else // _DEBUG (*(CtorFtnType)ctorFtn)(thisPtr, (BYTE*)pElemMT); #endif // _DEBUG offset += size; } END_CALL_TO_MANAGED(); #else // _X86_ // // This is quite a bit slower, but it is portable. // for (SIZE_T i =0; i < cElements; i++) { // Since GetSlot() is not idempotent and may have returned // a non-optimal entry-point the first time round. if (i == 1) { ctorFtn = pCanonMT->GetSlot(slot); } BYTE* thisPtr = (((BYTE*) OBJECTREFToObject (*arrayRef)) + offset); PREPARE_NONVIRTUAL_CALLSITE_USING_CODE(ctorFtn); DECLARE_ARGHOLDER_ARRAY(args, 2); args[ARGNUM_0] = PTR_TO_ARGHOLDER(thisPtr); args[ARGNUM_1] = PTR_TO_ARGHOLDER(pElemMT); // Instantiation argument if the type is generic CALL_MANAGED_METHOD_NORET(args); offset += size; } #endif // _X86_ }
//+---------------------------------------------------------------------------- // // 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); }