// static ThreadStore * ThreadStore::Create(RuntimeInstance * pRuntimeInstance) { NewHolder<ThreadStore> pNewThreadStore = new (nothrow) ThreadStore(); if (NULL == pNewThreadStore) return NULL; pNewThreadStore->m_SuspendCompleteEvent.CreateManualEvent(TRUE); pNewThreadStore->m_pRuntimeInstance = pRuntimeInstance; pNewThreadStore.SuppressRelease(); return pNewThreadStore; }
// Create a new thread // Parameters: // function - the function to be executed by the thread // param - parameters of the thread // affinity - processor affinity of the thread // Return: // true if it has succeeded, false if it has failed bool GCToOSInterface::CreateThread(GCThreadFunction function, void* param, GCThreadAffinity* affinity) { LIMITED_METHOD_CONTRACT; uint32_t thread_id; NewHolder<GCThreadStubParam> stubParam = new (nothrow) GCThreadStubParam(); if (stubParam == NULL) { return false; } stubParam->GCThreadFunction = function; stubParam->GCThreadParam = param; HANDLE gc_thread = Thread::CreateUtilityThread(Thread::StackSize_Medium, GCThreadStub, stubParam, CREATE_SUSPENDED, (DWORD*)&thread_id); if (!gc_thread) { return false; } stubParam.SuppressRelease(); SetThreadPriority(gc_thread, /* THREAD_PRIORITY_ABOVE_NORMAL );*/ THREAD_PRIORITY_HIGHEST ); #ifndef FEATURE_PAL if (affinity->Group != GCThreadAffinity::None) { _ASSERTE(affinity->Processor != GCThreadAffinity::None); GROUP_AFFINITY ga; ga.Group = (WORD)affinity->Group; ga.Reserved[0] = 0; // reserve must be filled with zero ga.Reserved[1] = 0; // otherwise call may fail ga.Reserved[2] = 0; ga.Mask = (size_t)1 << affinity->Processor; CPUGroupInfo::SetThreadGroupAffinity(gc_thread, &ga, NULL); } else if (affinity->Processor != GCThreadAffinity::None) { SetThreadAffinityMask(gc_thread, (DWORD_PTR)1 << affinity->Processor); } #endif // !FEATURE_PAL ResumeThread(gc_thread); CloseHandle(gc_thread); return true; }
HRESULT PropertyMap::Add(SString *pPropertyName, SBuffer *pPropertyValue) { _ASSERTE(pPropertyName != NULL); _ASSERTE(pPropertyValue != NULL); HRESULT hr = S_OK; NewHolder<PropertyEntry> pPropertyEntry; SAFE_NEW(pPropertyEntry, PropertyEntry); pPropertyEntry->SetPropertyName(pPropertyName); pPropertyEntry->SetPropertyValue(pPropertyValue); SHash<PropertyHashTraits>::Add(pPropertyEntry); pPropertyEntry.SuppressRelease(); Exit: return hr; }
HRESULT CCoreCLRBinderHelper::GetAssemblyIdentity(LPCSTR szTextualIdentity, BINDER_SPACE::ApplicationContext *pApplicationContext, NewHolder<AssemblyIdentityUTF8> &assemblyIdentityHolder) { HRESULT hr = S_OK; VALIDATE_ARG_RET(szTextualIdentity != NULL); EX_TRY { AssemblyIdentityUTF8 *pAssemblyIdentity = NULL; if (pApplicationContext != NULL) { // This returns a cached copy owned by application context hr = pApplicationContext->GetAssemblyIdentity(szTextualIdentity, &pAssemblyIdentity); if(SUCCEEDED(hr)) { assemblyIdentityHolder = pAssemblyIdentity; assemblyIdentityHolder.SuppressRelease(); } } else { SString sTextualIdentity; sTextualIdentity.SetUTF8(szTextualIdentity); // This is a private copy pAssemblyIdentity = new AssemblyIdentityUTF8(); hr = TextualIdentityParser::Parse(sTextualIdentity, pAssemblyIdentity); if(SUCCEEDED(hr)) { pAssemblyIdentity->PopulateUTF8Fields(); assemblyIdentityHolder = pAssemblyIdentity; } } } EX_CATCH_HRESULT(hr); return hr; }
//--------------------------------------------------------------------------------------- // // Initialize the static instance and lock. // HRESULT LOADEDMODULES::InitializeStatics() { HRESULT hr = S_OK; if (VolatileLoad(&s_pLoadedModules) == NULL) { // Initialize global read-write lock { NewHolder<UTSemReadWrite> pSemReadWrite = new (nothrow) UTSemReadWrite(); IfNullGo(pSemReadWrite); IfFailGo(pSemReadWrite->Init()); if (InterlockedCompareExchangeT<UTSemReadWrite *>(&m_pSemReadWrite, pSemReadWrite, NULL) == NULL) { // We won the initialization race pSemReadWrite.SuppressRelease(); } } // Initialize the global instance { NewHolder<LOADEDMODULES> pLoadedModules = new (nothrow) LOADEDMODULES(); IfNullGo(pLoadedModules); { LOCKWRITE(); if (VolatileLoad(&s_pLoadedModules) == NULL) { VolatileStore(&s_pLoadedModules, pLoadedModules.Extract()); } } } } ErrExit: return hr; } // LOADEDMODULES::InitializeStatics
//===================================================================================================================== HRESULT CLRPrivBinderAppX::BindAppXAssemblyByNameWorker( IAssemblyName * pIAssemblyName, DWORD dwAppXBindFlags, CLRPrivAssemblyAppX ** ppAssembly) { STANDARD_VM_CONTRACT; HRESULT hr = S_OK; fusion::logging::StatusScope logStatus(0, ID_FUSLOG_BINDING_STATUS_IMMERSIVE, &hr); VALIDATE_ARG_RET(pIAssemblyName != nullptr); VALIDATE_ARG_RET((dwAppXBindFlags & ABF_BindIL) == ABF_BindIL); VALIDATE_ARG_RET(ppAssembly != nullptr); DWORD dwContentType = AssemblyContentType_Default; IfFailRet(hr = fusion::util::GetProperty(pIAssemblyName, ASM_NAME_CONTENT_TYPE, &dwContentType)); if ((hr == S_OK) && (dwContentType != AssemblyContentType_Default)) { IfFailRet(CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT); } ReleaseHolder<CLRPrivAssemblyAppX> pAssembly; // Get the simple name. WCHAR wzSimpleName[_MAX_PATH]; DWORD cchSimpleName = _MAX_PATH; IfFailRet(pIAssemblyName->GetName(&cchSimpleName, wzSimpleName)); { // Look for previous successful bind. Host callouts are now forbidden. ForbidSuspendThreadCrstHolder lock(&m_MapReadLock); pAssembly = clr::SafeAddRef(m_NameToAssemblyMap.Lookup(wzSimpleName)); } if (pAssembly == nullptr) { ReleaseHolder<ICLRPrivResource> pResourceIL; ReleaseHolder<ICLRPrivResource> pResourceNI; // Create assembly identity using the simple name. For successful binds this will be updated // with the full assembly identity in the VerifyBind callback. NewHolder<AssemblyIdentity> pIdentity = new AssemblyIdentity(); IfFailRet(pIdentity->Initialize(wzSimpleName)); // // Check the head package first to see if this matches an EXE, then check // all packages to see if this matches a DLL. // WCHAR wzFilePath[_MAX_PATH]; { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); if (FAILED(hr)) { // Create simple name with .EXE extension WCHAR wzSimpleFileName[_MAX_PATH]; wcscpy_s(wzSimpleFileName, NumItems(wzSimpleFileName), wzSimpleName); wcscat_s(wzSimpleFileName, NumItems(wzSimpleFileName), W(".EXE")); // Search for the file using AppX::FileFileInCurrentPackage helper. UINT32 cchFilePath = NumItems(wzFilePath); hr = AppX::FindFileInCurrentPackage( wzSimpleFileName, &cchFilePath, wzFilePath, PACKAGE_FILTER_CLR_DEFAULT, (PCWSTR *)(void *)m_rgAltPaths, m_cAltPaths, m_pParentBinder != NULL ? AppX::FindFindInPackageFlags_SkipCurrentPackageGraph : AppX::FindFindInPackageFlags_None); } if (FAILED(hr)) { // Create simple name with .DLL extension WCHAR wzSimpleFileName[_MAX_PATH]; wcscpy_s(wzSimpleFileName, NumItems(wzSimpleFileName), wzSimpleName); wcscat_s(wzSimpleFileName, NumItems(wzSimpleFileName), W(".DLL")); // Search for the file using AppX::FileFileInCurrentPackage helper UINT32 cchFilePath = NumItems(wzFilePath); hr = AppX::FindFileInCurrentPackage( wzSimpleFileName, &cchFilePath, wzFilePath, PACKAGE_FILTER_CLR_DEFAULT, (PCWSTR *)(void *)m_rgAltPaths, m_cAltPaths, m_pParentBinder != NULL ? AppX::FindFindInPackageFlags_SkipCurrentPackageGraph : AppX::FindFindInPackageFlags_None); } if (SUCCEEDED(hr)) { fusion::logging::LogMessage(0, ID_FUSLOG_BINDING_STATUS_FOUND, wzFilePath); } else { // Cache the bind failure result before returning. Careful not to overwrite the bind result with the cache insertion result. HRESULT hrResult = hr; IfFailRet(CacheBindResult(pIdentity, hr)); if (hr == S_OK) { // Cache now owns identity object lifetime. pIdentity.SuppressRelease(); } hr = hrResult; } IfFailRet(hr); } NewHolder<CLRPrivResourcePathImpl> pResourcePath = new CLRPrivResourcePathImpl(wzFilePath); IfFailRet(pResourcePath->QueryInterface(__uuidof(ICLRPrivResource), (LPVOID*)&pResourceIL)); pResourcePath.SuppressRelease(); // Create an IBindResult and provide it to the new CLRPrivAssemblyAppX object. ReleaseHolder<IBindResult> pIBindResult = ToInterface<IBindResult>( new CLRPrivAssemblyBindResultWrapper(pIAssemblyName, wzFilePath, m_pFingerprintFactory)); // Create the new CLRPrivAssemblyAppX object. NewHolder<CLRPrivAssemblyAppX> pAssemblyObj = new CLRPrivAssemblyAppX(pIdentity, this, pResourceIL, pIBindResult); // // Check cache. If someone beat us then use it instead; otherwise add new ICLRPrivAssembly. // do { // Because the read lock must be taken within a ForbidSuspend region, use AddInPhases. if (m_NameToAssemblyMap.CheckAddInPhases<ForbidSuspendThreadCrstHolder, CrstHolder>( pAssemblyObj, m_MapReadLock, m_MapWriteLock, pAssemblyObj.GetValue())) { { // Careful not to allow the cache insertion result to overwrite the bind result. HRESULT hrResult = hr; IfFailRet(CacheBindResult(pIdentity, hr)); if (hr == S_OK) { // Cache now owns identity object lifetime, but ~CLRPrivBinderAssembly // can also remove the identity from the cache prior to cache deletion. pIdentity.SuppressRelease(); } hr = hrResult; } pAssembly = pAssemblyObj.Extract(); } else { ForbidSuspendThreadCrstHolder lock(&m_MapReadLock); pAssembly = clr::SafeAddRef(m_NameToAssemblyMap.Lookup(wzSimpleName)); } } while (pAssembly == nullptr); // Keep looping until we find the existing one, or add a new one } _ASSERTE(pAssembly != nullptr); if (((dwAppXBindFlags & ABF_BindNI) == ABF_BindNI) && m_fCanUseNativeImages) { // // Look to see if there's a native image available. // // Fire BindingNgenPhaseStart ETW event if enabled. { InlineSString<128> ssAssemblyName; FireEtwBindingNgenPhaseStart( (AppDomain::GetCurrentDomain()->GetId().m_dwId), LOADCTX_TYPE_HOSTED, ETWFieldUnused, ETWLoaderLoadTypeNotAvailable, NULL, FusionBind::GetAssemblyNameDisplayName(pIAssemblyName, ssAssemblyName, ASM_DISPLAYF_FULL).GetUnicode(), GetClrInstanceId()); } ReleaseHolder<IBindResult> pIBindResultIL; IfFailRet(pAssembly->GetIBindResult(&pIBindResultIL)); _ASSERTE(pIBindResultIL != nullptr); NewArrayHolder<WCHAR> wzZapSet = DuplicateStringThrowing(g_pConfig->ZapSet()); NativeConfigData cfgData = { wzZapSet, PEFile::GetNativeImageConfigFlags() }; IfFailRet(BindToNativeAssembly( pIBindResultIL, &cfgData, static_cast<IBindContext*>(this), fusion::logging::GetCurrentFusionBindLog())); // Ensure that the native image found above in BindToNativeAssembly is reported as existing in the CLRPrivAssembly object if (hr == S_OK) { ReleaseHolder<ICLRPrivResource> pNIImageResource; // This will make GetAvailableImageTypes return that a native image exists. IfFailRet(pAssembly->GetImageResource(ASSEMBLY_IMAGE_TYPE_NATIVE, NULL, &pNIImageResource)); #ifdef _DEBUG DWORD dwImageTypes; _ASSERTE(SUCCEEDED(pAssembly->GetAvailableImageTypes(&dwImageTypes))); _ASSERTE((dwImageTypes & ASSEMBLY_IMAGE_TYPE_NATIVE) == ASSEMBLY_IMAGE_TYPE_NATIVE); #endif } // Fire BindingNgenPhaseEnd ETW event if enabled. { InlineSString<128> ssAssemblyName; FireEtwBindingNgenPhaseEnd( (AppDomain::GetCurrentDomain()->GetId().m_dwId), LOADCTX_TYPE_HOSTED, ETWFieldUnused, ETWLoaderLoadTypeNotAvailable, NULL, FusionBind::GetAssemblyNameDisplayName(pIAssemblyName, ssAssemblyName, ASM_DISPLAYF_FULL).GetUnicode(), GetClrInstanceId()); } // BindToNativeAssembly can return S_FALSE, but this could be misleading. if (hr == S_FALSE) hr = S_OK; } if (SUCCEEDED(hr)) { *ppAssembly = pAssembly.Extract(); } return hr; }
// Given a PID attempt to find or create a DbgTransportSession instance to manage a connection to a runtime in // that process. Returns E_UNEXPECTED if the process can't be found. Also returns a handle that can be waited // on for process termination. HRESULT DbgTransportTarget::GetTransportForProcess(DWORD dwPID, DbgTransportSession **ppTransport, HANDLE *phProcessHandle) { RSLockHolder lock(&m_sLock); HRESULT hr = S_OK; ProcessEntry *entry = LocateProcessByPID(dwPID); if (entry == NULL) { NewHolder<ProcessEntry> newEntry = new(nothrow) ProcessEntry(); if (newEntry == NULL) return E_OUTOFMEMORY; NewHolder<DbgTransportSession> transport = new(nothrow) DbgTransportSession(); if (transport == NULL) { return E_OUTOFMEMORY; } HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); if (hProcess == NULL) { transport->Shutdown(); return HRESULT_FROM_GetLastError(); } // Initialize it (this immediately starts the remote connection process). hr = transport->Init(dwPID, hProcess); if (FAILED(hr)) { transport->Shutdown(); CloseHandle(hProcess); return hr; } entry = newEntry; newEntry.SuppressRelease(); entry->m_dwPID = dwPID; entry->m_hProcess = hProcess; entry->m_transport = transport; transport.SuppressRelease(); entry->m_cProcessRef = 0; // Adding new entry to the list. entry->m_pNext = m_pProcessList; m_pProcessList = entry; } entry->m_cProcessRef++; _ASSERTE(entry->m_cProcessRef > 0); _ASSERTE(entry->m_transport != NULL); _ASSERTE(entry->m_hProcess > 0); *ppTransport = entry->m_transport; if (!DuplicateHandle(GetCurrentProcess(), entry->m_hProcess, GetCurrentProcess(), phProcessHandle, 0, // ignored since we are going to pass DUPLICATE_SAME_ACCESS FALSE, DUPLICATE_SAME_ACCESS)) { return HRESULT_FROM_GetLastError(); } return hr; }