diff options
Diffstat (limited to 'src/vm/ceemain.cpp')
-rw-r--r-- | src/vm/ceemain.cpp | 1830 |
1 files changed, 91 insertions, 1739 deletions
diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp index ca819ecbfd..6b0c0dfbba 100644 --- a/src/vm/ceemain.cpp +++ b/src/vm/ceemain.cpp @@ -39,25 +39,25 @@ // //************************************************************************************************* // -// * Introduction to the rutnime file:../../doc/BookOfTheRuntime/Introduction/BOTR%20Introduction.docx +// * Introduction to the runtime file:../../Documentation/botr/botr-faq.md // // #MajorDataStructures. The major data structures associated with the runtime are // * code:Thread (see file:threads.h#ThreadClass) - the additional thread state the runtime needs. // * code:AppDomain - The managed version of a process -// * code:Assembly - The unit of deployment and versioing (may be several DLLs but often is only one). -// * code:Module -represents a Module (DLL or EXE). +// * code:Assembly - The unit of deployment and versioning (may be several DLLs but often is only one). +// * code:Module - represents a Module (DLL or EXE). // * code:MethodTable - represents the 'hot' part of a type (needed during normal execution) // * code:EEClass - represents the 'cold' part of a type (used during compilation, interop, ...) // * code:MethodDesc - represents a Method // * code:FieldDesc - represents a Field. -// * code:Object - represents a object on the GC heap alloated with code:Alloc +// * code:Object - represents a object on the GC heap allocated with code:Alloc // // * ECMA specifications // * Partition I Concepts // http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20I%20Architecture.doc // * Partition II Meta Data // http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20II%20Metadata.doc -// * Parition III IL +// * Partition III IL // http://download.microsoft.com/download/D/C/1/DC1B219F-3B11-4A05-9DA3-2D0F98B20917/Partition%20III%20CIL.doc // // * Serge Liden (worked on the CLR and owned ILASM / ILDASM for a long time wrote a good book on IL @@ -76,7 +76,7 @@ // * code:ICorJitCompiler#EEToJitInterface - This is the interface from the the EE to the Just in time (JIT) // compiler. The interface to the JIT is relatively simple (compileMethod), however the EE provides a // rich set of callbacks so the JIT can get all the information it needs. See also -// file:../../doc/BookOfTheRuntime/JIT/JIT%20Design.doc for general information on the JIT. +// file:../../Documentation/botr/ryujit-overview.md for general information on the JIT. // // * code:VirtualCallStubManager - This is the main class that implements interface dispatch // @@ -85,36 +85,22 @@ // and will call the JIT compiler if the code does not yet exist. // // * NGEN - NGen stands for Native code GENeration and it is the runtime way of precomiling IL and IL -// Meta-data into native code and runtime data structures. See -// file:../../doc/BookOfTheRuntime/NGEN/NGENDesign.doc for an overview. At compilation time the most +// Meta-data into native code and runtime data structures. At compilation time the most // fundamental data structures is the code:ZapNode which represents something that needs to go into the // NGEN image. // // * What is cooperative / preemtive mode ? file:threads.h#CooperativeMode and -// file:threads.h#SuspendingTheRuntime -// * Garbage collection - file:gc.cpp#Overview +// file:threads.h#SuspendingTheRuntime and file:../../Documentation/botr/threading.md +// * Garbage collection - file:gc.cpp#Overview and file:../../Documentation/botr/garbage-collection.md // * code:AppDomain - The managed version of a process. -// * Calling Into the runtime (FCALLs QCalls) file:../../doc/BookOfTheRuntime/mscorlib/mscorlibDesign.doc -// * Exceptions - file:../../doc/BookOfTheRuntime/ManagedEH\Design.doc. The most important routine to start -// with is code:COMPlusFrameHandler which is the routine that we hook up to get called when an unanaged +// * Calling Into the runtime (FCALLs QCalls) file:../../Documentation/botr/mscorlib.md +// * Exceptions - file:../../Documentation/botr/exceptions.md. The most important routine to start +// with is code:COMPlusFrameHandler which is the routine that we hook up to get called when an unmanaged // exception happens. -// * Constrain Execution Regions (reliability) file:../../doc/BookOfTheRuntime/CER/CERDesign.doc) -// * Assembly Loading file:../../doc/BookOfTheRuntime/AssemblyLoader/AssemblyLoader.doc -// * Fusion and loading files file:../../doc/BookOfTheRuntime/AssemblyLoader/FusionDesign.doc -// * Strings file:../../doc/BookOfTheRuntime/BCL/SystemStringDesign.doc -// * Profiling file:../../doc/BookOfTheRuntime/DiagnosticServices/ProfilingAPIDesign.doc -// * Remoting file:../../doc/BookOfTheRuntime/EERemotingSupport/RemotingDesign.doc -// * Managed Debug Assitants file:../../doc/BookOfTheRuntime/MDA/MDADesign.doc +// * Assembly Loading file:../../Documentation/botr/type-loader.md +// * Profiling file:../../Documentation/botr/profiling.md and file:../../Documentation/botr/profilability.md // * FCALLS QCALLS (calling into the runtime from managed code) -// file:../../doc/BookOfTheRuntime/Mscorlib/MscorlibDesign.doc -// * Reflection file:../../doc/BookOfTheRuntime/Reflection/ReflectionDesign.doc -// * Security -// * file:../../doc/BookOfTheRuntime/RuntimeSecurity/RuntimeSecurityDesign.doc -// * file:../../doc/BookOfTheRuntime/LoadtimeSecurity/DeclarativeSecurity-Design.doc -// * file:../../doc/BookOfTheRuntime/LoadtimeSecurity/StrongName.doc -// * file:../../doc/BookOfTheRuntime/RuntimeSecurity/ClickOnce Activation.doc -// * file:../../doc/BookOfTheRuntime/RuntimeSecurity/Cryptography.doc -// * file:../../doc/BookOfTheRuntime/RuntimeSecurity/DemandEvalDesign.doc +// file:../../Documentation/botr/mscorlib.md // * Event Tracing for Windows // * file:../inc/eventtrace.h#EventTracing - // * This is the main file dealing with event tracing in CLR @@ -158,13 +144,9 @@ #include "eedbginterfaceimpl.h" #include "debugdebugger.h" #include "cordbpriv.h" -#ifdef FEATURE_REMOTING -#include "remoting.h" -#endif #include "comdelegate.h" #include "appdomain.hpp" #include "perfcounters.h" -#include "rwlock.h" #ifdef FEATURE_IPCMAN #include "ipcmanagerinterface.h" #endif // FEATURE_IPCMAN @@ -213,10 +195,6 @@ #include "bbsweep.h" -#ifndef FEATURE_CORECLR -#include <metahost.h> -#include "assemblyusagelogmanager.h" -#endif #ifdef FEATURE_COMINTEROP #include "runtimecallablewrapper.h" @@ -244,19 +222,15 @@ #include "interpreter.h" #endif // FEATURE_INTERPRETER -#ifndef FEATURE_FUSION #include "../binder/inc/coreclrbindercommon.h" -#endif // !FEATURE_FUSION -#ifdef FEATURE_UEF_CHAINMANAGER -// This is required to register our UEF callback with the UEF chain manager -#include <mscoruefwrapper.h> -#endif // FEATURE_UEF_CHAINMANAGER #ifdef FEATURE_PERFMAP #include "perfmap.h" #endif +#include "eventpipe.h" + #ifndef FEATURE_PAL // Included for referencing __security_cookie #include "process.h" @@ -275,21 +249,7 @@ static HRESULT GetThreadUICultureNames(__inout StringArrayList* pCultureNames); #endif // !CROSSGEN_COMPILE HRESULT EEStartup(COINITIEE fFlags); -#ifdef FEATURE_FUSION -extern "C" HRESULT STDMETHODCALLTYPE InitializeFusion(); -#endif -#ifdef FEATURE_MIXEDMODE -HRESULT PrepareExecuteDLLForThunk(HINSTANCE hInst, - DWORD dwReason, - LPVOID lpReserved); -#endif // FEATURE_MIXEDMODE -#ifndef FEATURE_CORECLR -BOOL STDMETHODCALLTYPE ExecuteDLL(HINSTANCE hInst, - DWORD dwReason, - LPVOID lpReserved, - BOOL fFromThunk); -#endif // !FEATURE_CORECLR BOOL STDMETHODCALLTYPE ExecuteEXE(HMODULE hMod); BOOL STDMETHODCALLTYPE ExecuteEXE(__in LPWSTR pImageNameIn); @@ -305,12 +265,6 @@ extern "C" HRESULT __cdecl CorDBGetInterface(DebugInterface** rcInterface); #endif // !CROSSGEN_COMPILE -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) - -// Pointer to the activated CLR interface provided by the shim. -ICLRRuntimeInfo *g_pCLRRuntime = NULL; - -#endif // !FEATURE_CORECLR && !CROSSGEN_COMPILE extern "C" IExecutionEngine* __stdcall IEE(); @@ -391,7 +345,7 @@ HRESULT EnsureEEStarted(COINITIEE flags) { BEGIN_ENTRYPOINT_NOTHROW; -#if defined(FEATURE_CORECLR) && defined(FEATURE_APPX) && !defined(CROSSGEN_COMPILE) +#if defined(FEATURE_APPX) && !defined(CROSSGEN_COMPILE) STARTUP_FLAGS startupFlags = CorHost2::GetStartupFlags(); // On CoreCLR, the host is in charge of determining whether the process is AppX or not. AppX::SetIsAppXProcess(!!(startupFlags & STARTUP_APPX_APP_MODEL)); @@ -403,15 +357,6 @@ HRESULT EnsureEEStarted(COINITIEE flags) REGUTIL::InitOptionalConfigCache(); #endif -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - IHostTaskManager *pHostTaskManager = CorHost2::GetHostTaskManager(); - if (pHostTaskManager) - { - BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); - pHostTaskManager->BeginThreadAffinity(); - END_SO_TOLERANT_CODE_CALLING_HOST; - } -#endif // FEATURE_INCLUDE_ALL_INTERFACES BOOL bStarted=FALSE; @@ -442,14 +387,6 @@ HRESULT EnsureEEStarted(COINITIEE flags) } } -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - if (pHostTaskManager) - { - BEGIN_SO_TOLERANT_CODE_CALLING_HOST(GetThread()); - pHostTaskManager->EndThreadAffinity(); - END_SO_TOLERANT_CODE_CALLING_HOST; - } -#endif // FEATURE_INCLUDE_ALL_INTERFACES #ifdef FEATURE_TESTHOOKS if(bStarted) TESTHOOKCALL(RuntimeStarted(RTS_INITIALIZED)); @@ -528,58 +465,7 @@ static BOOL WINAPI DbgCtrlCHandler(DWORD dwCtrlType) // A host can specify that it only wants one version of hosting interface to be used. BOOL g_singleVersionHosting; -#ifndef FEATURE_CORECLR -HRESULT STDMETHODCALLTYPE -SetRuntimeInfo( - IUnknown * pUnk, - STARTUP_FLAGS dwStartupFlags, - LPCWSTR pwzHostConfig, - const CoreClrCallbacks ** ppClrCallbacks) -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - ENTRY_POINT; - PRECONDITION(CheckPointer(pUnk)); - PRECONDITION(CheckPointer(pwzHostConfig, NULL_OK)); - } CONTRACTL_END; - - ICLRRuntimeInfo *pRuntime; - HRESULT hr; - - IfFailGo(pUnk->QueryInterface(IID_ICLRRuntimeInfo, (LPVOID *)&pRuntime)); - - IfFailGo(CorHost2::SetFlagsAndHostConfig(dwStartupFlags, pwzHostConfig, FALSE)); - if (InterlockedCompareExchangeT(&g_pCLRRuntime, pRuntime, NULL) != NULL) - { - // already set, release this one - pRuntime->Release(); - } - *ppClrCallbacks = &GetClrCallbacks(); - -ErrExit: - return hr; -} -#endif // !FEATURE_CORECLR - -#ifndef FEATURE_CORECLR -HRESULT InitializeHostConfigFile() -{ - CONTRACTL { - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - INJECT_FAULT(return E_OUTOFMEMORY); - } CONTRACTL_END; - - g_pszHostConfigFile = CorHost2::GetHostConfigFile(); - g_dwHostConfigFile = (g_pszHostConfigFile == NULL ? 0 : wcslen(g_pszHostConfigFile)); - - return S_OK; -} -#endif // !FEATURE_CORECLR void InitializeStartupFlags() { @@ -591,56 +477,15 @@ void InitializeStartupFlags() STARTUP_FLAGS flags = CorHost2::GetStartupFlags(); -#ifndef FEATURE_CORECLR - // If we are running under a requested performance default mode, honor any changes to startup flags - // In the future, we could make this conditional on the host telling us which subset of flags is - // valid to override. See file:PerfDefaults.h - flags = PerformanceDefaults::GetModifiedStartupFlags(flags); -#endif // !FEATURE_CORECLR if (flags & STARTUP_CONCURRENT_GC) g_IGCconcurrent = 1; else g_IGCconcurrent = 0; -#ifndef FEATURE_CORECLR // TODO: We can remove this. Retaining it now just to be safe - if (flags & STARTUP_SINGLE_VERSION_HOSTING_INTERFACE) - { - g_singleVersionHosting = TRUE; - } - -#ifndef FEATURE_CORECLR - g_pConfig->SetDisableCommitThreadStack(!CLRHosted() || (flags & STARTUP_DISABLE_COMMITTHREADSTACK)); -#else - g_pConfig->SetDisableCommitThreadStack(true); -#endif - - if(flags & STARTUP_LEGACY_IMPERSONATION) - g_pConfig->SetLegacyImpersonationPolicy(); - - if(flags & STARTUP_ALWAYSFLOW_IMPERSONATION) - g_pConfig->SetAlwaysFlowImpersonationPolicy(); - - if(flags & STARTUP_HOARD_GC_VM) - g_IGCHoardVM = 1; - else - g_IGCHoardVM = 0; - -#ifdef GCTRIMCOMMIT - if (flags & STARTUP_TRIM_GC_COMMIT) - g_IGCTrimCommit = 1; - else - g_IGCTrimCommit = 0; -#endif - - if(flags & STARTUP_ETW) - g_fEnableETW = TRUE; - - if(flags & STARTUP_ARM) - g_fEnableARM = TRUE; -#endif // !FEATURE_CORECLR InitializeHeapType((flags & STARTUP_SERVER_GC) != 0); + g_heap_type = (flags & STARTUP_SERVER_GC) == 0 ? GC_HEAP_WKS : GC_HEAP_SVR; #ifdef FEATURE_LOADER_OPTIMIZATION g_dwGlobalSharePolicy = (flags&STARTUP_LOADER_OPTIMIZATION_MASK)>>1; @@ -740,37 +585,23 @@ void InitGSCookie() } } -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) -void InitAssemblyUsageLogManager() -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } CONTRACTL_END; - - HRESULT hr = S_OK; - - g_pIAssemblyUsageLogGac = NULL; - - AssemblyUsageLogManager::Config config; +Volatile<BOOL> g_bIsGarbageCollectorFullyInitialized = FALSE; - config.wszLogDir = NULL; - config.cLogBufferSize = 32768; -#ifdef FEATURE_APPX - config.uiLogRefreshInterval = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NGenAssemblyUsageLogRefreshInterval); -#endif +void SetGarbageCollectorFullyInitialized() +{ + LIMITED_METHOD_CONTRACT; - NewArrayHolder<WCHAR> szCustomLogDir(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NGenAssemblyUsageLog)); - config.wszLogDir = szCustomLogDir; + g_bIsGarbageCollectorFullyInitialized = TRUE; +} - AssemblyUsageLogManager::Init(&config); +// Tells whether the garbage collector is fully initialized +// Stronger than IsGCHeapInitialized +BOOL IsGarbageCollectorFullyInitialized() +{ + LIMITED_METHOD_CONTRACT; - // Once the logger is initialized, create a log object for logging GAC loads. - AssemblyUsageLogManager::GetUsageLogForContext(W("fusion"), W("GAC"), &g_pIAssemblyUsageLogGac); + return g_bIsGarbageCollectorFullyInitialized; } -#endif // --------------------------------------------------------------------------- // %%Function: EEStartupHelper @@ -845,10 +676,6 @@ void EEStartupHelper(COINITIEE fFlags) if (!g_pConfig) { IfFailGo(EEConfig::Setup()); -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) - IfFailGo(InitializeHostConfigFile()); - IfFailGo(g_pConfig->SetupConfiguration()); -#endif // !FEATURE_CORECLR && !CROSSGEN_COMPILE } #ifndef CROSSGEN_COMPILE @@ -858,11 +685,6 @@ void EEStartupHelper(COINITIEE fFlags) NumaNodeInfo::InitNumaNodeInfo(); CPUGroupInfo::EnsureInitialized(); -#ifndef FEATURE_CORECLR - // Check in EEConfig whether a workload-specific set of performance defaults have been requested - // This needs to be done before InitializeStartupFlags in case one is to be overridden - PerformanceDefaults::InitializeForScenario(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_PerformanceScenario)); -#endif // Initialize global configuration settings based on startup flags // This needs to be done before the EE has started @@ -897,10 +719,6 @@ void EEStartupHelper(COINITIEE fFlags) #endif // CROSSGEN_COMPILE -#ifndef FEATURE_CORECLR - // Ensure initialization of Apphacks environment variables - GetGlobalCompatibilityFlags(); -#endif // !FEATURE_CORECLR #ifdef STRESS_LOG if (REGUTIL::GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_StressLog, g_pConfig->StressLog ()) != 0) { @@ -935,15 +753,8 @@ void EEStartupHelper(COINITIEE fFlags) #endif // Fusion -#ifdef FEATURE_FUSION - { - ETWOnStartup (FusionInit_V1, FusionInitEnd_V1); - IfFailGoLog(InitializeFusion()); - } -#else // FEATURE_FUSION // Initialize the general Assembly Binder infrastructure IfFailGoLog(CCoreCLRBinderHelper::Init()); -#endif // FEATURE_FUSION if (g_pConfig != NULL) { @@ -988,21 +799,10 @@ void EEStartupHelper(COINITIEE fFlags) #ifndef CROSSGEN_COMPILE -#if defined(STRESS_HEAP) && defined(_DEBUG) && !defined(FEATURE_CORECLR) - // TODO: is this still an issue? - // There is a race that causes random AVs on dual proc boxes - // that we suspect is due to memory coherancy problems (see Whidbey bug 2360) - // Avoid the issue by making the box effectively single proc. - if (GCStress<cfg_instr>::IsEnabled() && - g_SystemInfo.dwNumberOfProcessors > 1) - SetProcessAffinityMask(GetCurrentProcess(), - 1 << (DbgGetEXETimeStamp() % g_SystemInfo.dwNumberOfProcessors)); -#endif // STRESS_HEAP && _DEBUG && !FEATURE_CORECLR #ifdef FEATURE_PREJIT - // Initialize the sweeper thread. THis is violating our rules with hosting - // so we only do it in the non-hosted case - if (g_pConfig->GetZapBBInstr() != NULL && !CLRTaskHosted()) + // Initialize the sweeper thread. + if (g_pConfig->GetZapBBInstr() != NULL) { DWORD threadID; HANDLE hBBSweepThread = ::CreateThread(NULL, @@ -1065,14 +865,14 @@ void EEStartupHelper(COINITIEE fFlags) #ifndef CROSSGEN_COMPILE + InitializeGarbageCollector(); + // Initialize remoting -#ifdef FEATURE_REMOTING - CRemotingServices::Initialize(); -#endif // FEATURE_REMOTING - // weak_short, weak_long, strong; no pin - if (!Ref_Initialize()) + if (!GCHandleTableUtilities::GetGCHandleTable()->Initialize()) + { IfFailGo(E_OUTOFMEMORY); + } // Initialize contexts Context::Initialize(); @@ -1080,16 +880,6 @@ void EEStartupHelper(COINITIEE fFlags) g_pEEShutDownEvent = new CLREvent(); g_pEEShutDownEvent->CreateManualEvent(FALSE); -#ifdef FEATURE_RWLOCK - // Initialize RWLocks - CRWLock::ProcessInit(); -#endif // FEATURE_RWLOCK - -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - // Initialize debugger manager - CCLRDebugManager::ProcessInit(); -#endif // FEATURE_INCLUDE_ALL_INTERFACES - #ifdef FEATURE_IPCMAN // Initialize CCLRSecurityAttributeManager CCLRSecurityAttributeManager::ProcessInit(); @@ -1099,11 +889,6 @@ void EEStartupHelper(COINITIEE fFlags) GCInterface::m_MemoryPressureLock.Init(CrstGCMemoryPressure); -#ifndef FEATURE_CORECLR - // Initialize Assembly Usage Logger - InitAssemblyUsageLogManager(); -#endif - #endif // CROSSGEN_COMPILE // Setup the domains. Threads are started in a default domain. @@ -1122,6 +907,10 @@ void EEStartupHelper(COINITIEE fFlags) #ifndef CROSSGEN_COMPILE + // This isn't done as part of InitializeGarbageCollector() above because thread + // creation requires AppDomains to have been set up. + FinalizerThread::FinalizerThreadCreate(); + #ifndef FEATURE_PAL // Watson initialization must precede InitializeDebugger() and InstallUnhandledExceptionFilter() // because on CoreCLR when Waston is enabled, debugging service needs to be enabled and UEF will be used. @@ -1225,7 +1014,14 @@ void EEStartupHelper(COINITIEE fFlags) } #endif - InitializeGarbageCollector(); + // This isn't done as part of InitializeGarbageCollector() above because it + // requires write barriers to have been set up on x86, which happens as part + // of InitJITHelpers1. + hr = g_pGCHeap->Initialize(); + IfFailGo(hr); + + // Now we really have fully initialized the garbage collector + SetGarbageCollectorFullyInitialized(); InitializePinHandleTable(); @@ -1238,10 +1034,12 @@ void EEStartupHelper(COINITIEE fFlags) SystemDomain::System()->DefaultDomain())); SystemDomain::System()->PublishAppDomainAndInformDebugger(SystemDomain::System()->DefaultDomain()); #endif - -#ifndef FEATURE_CORECLR - ExistingOobAssemblyList::Init(); -#endif + +#ifdef FEATURE_PERFTRACING + // Initialize the event pipe and start it if requested. + EventPipe::Initialize(); + EventPipe::EnableOnStartup(); +#endif // FEATURE_PERFTRACING #endif // CROSSGEN_COMPILE @@ -1329,12 +1127,10 @@ void EEStartupHelper(COINITIEE fFlags) } //For a similar reason, let's not run VerifyAllOnLoad either. -#ifdef FEATURE_CORECLR if (g_pConfig->VerifyModulesOnLoad()) { SystemDomain::SystemModule()->VerifyAllMethods(); } -#endif //FEATURE_CORECLR // Perform mscorlib consistency check if requested g_Mscorlib.CheckExtended(); @@ -1595,11 +1391,6 @@ static void ExternalShutdownHelper(int exitCode, ShutdownCompleteAction sca) // process exit code. This can be modified by the app via System.SetExitCode(). SetLatchedExitCode(exitCode); -#ifndef FEATURE_CORECLR // no shim - // Bump up the ref-count on the module - for (int i =0; i<6; i++) - CLRLoadLibrary(MSCOREE_SHIM_W); -#endif // FEATURE_CORECLR ForceEEShutdown(sca); @@ -1671,12 +1462,6 @@ BOOL IsRuntimeStarted(DWORD *pdwStartupFlags) if (pdwStartupFlags != NULL) // this parameter is optional { *pdwStartupFlags = 0; -#ifndef FEATURE_CORECLR - if (g_fEEStarted) - { - *pdwStartupFlags = CorHost2::GetStartupFlags(); - } -#endif } return g_fEEStarted; } @@ -1791,7 +1576,7 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) ETW::EnumerationLog::ProcessShutdown(); } -#if defined(FEATURE_CAS_POLICY) || defined(FEATURE_COMINTEROP) +#if defined(FEATURE_COMINTEROP) // Get the current thread. Thread * pThisThread = GetThread(); #endif @@ -1869,14 +1654,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) fFinalizeOK = FinalizerThread::FinalizerThreadWatchDog(); } -#ifndef FEATURE_CORECLR - if (!g_fFastExitProcess) - { - // Log usage data to disk. (Only do this in normal shutdown scenarios, and not involving ngen) - if (!IsCompilationProcess()) - AssemblyUsageLogManager::GenerateLog(AssemblyUsageLogManager::GENERATE_LOG_FLAGS_NONE); - } -#endif // Ok. Let's stop the EE. if (!g_fProcessDetach) @@ -1931,6 +1708,11 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) PerfMap::Destroy(); #endif +#ifdef FEATURE_PERFTRACING + // Shutdown the event pipe. + EventPipe::Shutdown(); +#endif // FEATURE_PERFTRACING + #ifdef FEATURE_PREJIT { // If we're doing basic block profiling, we need to write the log files to disk. @@ -1939,8 +1721,19 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) if (!fIBCLoggingDone) { if (g_IBCLogger.InstrEnabled()) - Module::WriteAllModuleProfileData(true); + { + Thread * pThread = GetThread(); + ThreadLocalIBCInfo* pInfo = pThread->GetIBCInfo(); + // Acquire the Crst lock before creating the IBCLoggingDisabler object. + // Only one thread at a time can be processing an IBC logging event. + CrstHolder lock(g_IBCLogger.GetSync()); + { + IBCLoggingDisabler disableLogging( pInfo ); // runs IBCLoggingDisabler::DisableLogging + + Module::WriteAllModuleProfileData(true); + } + } fIBCLoggingDone = TRUE; } } @@ -1990,22 +1783,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) } #endif // PROFILING_SUPPORTED -#ifndef FEATURE_CORECLR - // CoEEShutDownCOM moved to - // the Finalizer thread. See bug 87809 - if (!g_fProcessDetach && !g_fFastExitProcess) - { - g_fEEShutDown |= ShutDown_COM; - if (fFinalizeOK) - { - FinalizerThread::FinalizerThreadWatchDog(); - } - } -#ifdef _DEBUG - else - g_fEEShutDown |= ShutDown_COM; -#endif -#endif //FEATURE_CORECLR #ifdef _DEBUG g_fEEShutDown |= ShutDown_SyncBlock; @@ -2015,15 +1792,6 @@ void STDMETHODCALLTYPE EEShutDownHelper(BOOL fIsDllUnloading) // because we are shutting down. CONTRACT_VIOLATION(ModeViolation); -#ifdef FEATURE_CAS_POLICY - // Save the security policy cache as necessary. - if (!g_fProcessDetach || pThisThread != NULL) - { - // If process shutdown has started, it is not safe to create Thread object which is needed - // by the following call. - Security::SaveCache(); - } -#endif #ifdef FEATURE_COMINTEROP // We need to call CoUninitialize in part one to ensure orderly shutdown of COM dlls. if (!g_fFastExitProcess) @@ -2112,7 +1880,7 @@ part2: #ifdef SHOULD_WE_CLEANUP if (!g_fFastExitProcess) { - Ref_Shutdown(); // shut down the handle table + GCHandleTableUtilities::GetGCHandleTable()->Shutdown(); } #endif /* SHOULD_WE_CLEANUP */ @@ -2662,774 +2430,6 @@ void STDMETHODCALLTYPE CoUninitializeEE(BOOL fIsDllUnloading) } -#ifndef FEATURE_CORECLR -//***************************************************************************** -// This entry point is called from the native DllMain of the loaded image. -// This gives the COM+ loader the chance to dispatch the loader event. The -// first call will cause the loader to look for the entry point in the user -// image. Subsequent calls will dispatch to either the user's DllMain or -// their Module derived class. -//***************************************************************************** -BOOL STDMETHODCALLTYPE _CorDllMain( // TRUE on success, FALSE on error. - HINSTANCE hInst, // Instance handle of the loaded module. - DWORD dwReason, // Reason for loading. - LPVOID lpReserved // Unused. - ) -{ - STATIC_CONTRACT_NOTHROW; - //STATIC_CONTRACT_GC_TRIGGERS; - STATIC_CONTRACT_ENTRY_POINT; - - //BEGIN_ENTRYPOINT_NOTHROW; - - struct Param - { - HINSTANCE hInst; - DWORD dwReason; - LPVOID lpReserved; - BOOL retval; - } param; - param.hInst = hInst; - param.dwReason = dwReason; - param.lpReserved = lpReserved; - param.retval = FALSE; - - // Can't use PAL_TRY/EX_TRY here as they access the ClrDebugState which gets blown away as part of the - // PROCESS_DETACH path. Must use special PAL_TRY_FOR_DLLMAIN, passing the reason were in the DllMain. - PAL_TRY_FOR_DLLMAIN(Param *, pParam, ¶m, pParam->dwReason) - { -#ifdef _DEBUG - if (CLRTaskHosted() && - ((pParam->dwReason == DLL_PROCESS_ATTACH && pParam->lpReserved == NULL) || // LoadLibrary of a managed dll - (pParam->dwReason == DLL_PROCESS_DETACH && pParam->lpReserved == NULL) // FreeLibrary of a managed dll - )) { - // OS loader lock is being held by the current thread. We can not allow the fiber - // to be rescheduled here while processing DllMain for managed dll. -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - IHostTask *pTask = GetCurrentHostTask(); - if (pTask) { - Thread *pThread = GetThread(); - _ASSERTE (pThread); - _ASSERTE (pThread->HasThreadAffinity()); - } -#endif // FEATURE_INCLUDE_ALL_INTERFACES - } -#endif - // Since we're in _CorDllMain, we know that we were not called because of a - // bootstrap thunk, since they will call CorDllMainForThunk. Because of this, - // we can pass FALSE for the fFromThunk parameter. - pParam->retval = ExecuteDLL(pParam->hInst,pParam->dwReason,pParam->lpReserved, FALSE); - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - } - PAL_ENDTRY; - - //END_ENTRYPOINT_NOTHROW; - - return param.retval; -} - -#endif // !FEATURE_CORECLR - -#ifdef FEATURE_MIXEDMODE -//***************************************************************************** -void STDMETHODCALLTYPE CorDllMainForThunk(HINSTANCE hInst, HINSTANCE hInstShim) -{ - - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_GC_TRIGGERS; - - - g_fEEIJWStartup = TRUE; - - { - - // If no managed thread exists, then we need to call the prepare method - // to try and startup the runtime and/or create a managed thread object - // so that installing an unwind and continue handler below is possible. - // If we fail to startup or create a thread, we'll raise the basic - // EXCEPTION_COMPLUS exception. - if (GetThread() == NULL) - { - HRESULT hr; - // Since this method is only called if a bootstrap thunk is invoked, we - // know that passing TRUE for fFromThunk is the correct value. - if (FAILED(hr = PrepareExecuteDLLForThunk(hInst, 0, NULL))) - { - RaiseComPlusException(); - } - } - - } - - INSTALL_UNWIND_AND_CONTINUE_HANDLER; - - // We're actually going to run some managed code and we're inside the loader lock. - // There may be a customer debug probe enabled that prevents this. - CanRunManagedCode(hInst); - - // Since this method is only called if a bootstrap thunk is invoked, we - // know that passing TRUE for fFromThunk is the correct value. - ExecuteDLL(hInst, 0, NULL, TRUE); - - UNINSTALL_UNWIND_AND_CONTINUE_HANDLER; - -} -#endif // FEATURE_MIXEDMODE - - -#ifndef FEATURE_CORECLR - -// This function will do some additional PE Checks to make sure everything looks good. -// We must do these before we run any managed code (that's why we can't do them in PEVerifier, as -// managed code is used to determine the policy settings) -HRESULT DoAdditionalPEChecks(HINSTANCE hInst) -{ - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_GC_TRIGGERS; - - struct Param - { - HINSTANCE hInst; - HRESULT hr; - } param; - param.hInst = hInst; - param.hr = S_OK; - - PAL_TRY(Param *, pParam, ¶m) - { - PEDecoder pe(pParam->hInst); - - if (!pe.CheckWillCreateGuardPage()) - pParam->hr = COR_E_BADIMAGEFORMAT; - } - PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - } - PAL_ENDTRY - - return param.hr; -} - -//***************************************************************************** -// This entry point is called from the native entry point of the loaded -// executable image. This simply calls into _CorExeMainInternal, the real -// entry point inside a filter to trigger unhandled exception processing in the -// event an exception goes unhandled, independent of the OS UEF mechanism. -//***************************************************************************** -__int32 STDMETHODCALLTYPE _CorExeMain( // Executable exit code. - ) -{ - STATIC_CONTRACT_GC_TRIGGERS; - STATIC_CONTRACT_THROWS; - - // We really have nothing to share with our filter at this point. - struct Param - { - PVOID pData; - } param; - param.pData = NULL; - - PAL_TRY(Param*, _pParam, ¶m) - { - // Call the real function that will invoke the managed entry point - _CorExeMainInternal(); - } - PAL_EXCEPT_FILTER(EntryPointFilter) - { - LOG((LF_STARTUP, LL_INFO10, "EntryPointFilter returned EXCEPTION_EXECUTE_HANDLER!")); - } - PAL_ENDTRY; - - return 0; -} - -//***************************************************************************** -// This entry point is called from _CorExeMain. If an exception goes unhandled -// from here, we will trigger unhandled exception processing in _CorExeMain. -// -// The command line arguments and other entry point data -// will be gathered here. The entry point for the user image will be found -// and handled accordingly. -//***************************************************************************** -__int32 STDMETHODCALLTYPE _CorExeMainInternal( // Executable exit code. - ) -{ - STATIC_CONTRACT_GC_TRIGGERS; - STATIC_CONTRACT_THROWS; - STATIC_CONTRACT_ENTRY_POINT; - - // Yes, CorExeMain needs throws. If an exception passes through here, it will cause the - // "The application has generated an unhandled exception" dialog and offer to debug. - - BEGIN_ENTRYPOINT_THROWS; - - // Make sure PE file looks ok - HRESULT hr; - { - // We are early in the process, if we get an SO here we will just rip - CONTRACT_VIOLATION(SOToleranceViolation); - if (FAILED(hr = DoAdditionalPEChecks(WszGetModuleHandle(NULL)))) - { - GCX_PREEMP(); - VMDumpCOMErrors(hr); - SetLatchedExitCode (-1); - goto exit; - } - } - - g_fEEManagedEXEStartup = TRUE; - // Before we initialize the EE, make sure we've snooped for all EE-specific - // command line arguments that might guide our startup. - WCHAR *pCmdLine = WszGetCommandLine(); - HRESULT result = CorCommandLine::SetArgvW(pCmdLine); - - if (SUCCEEDED(result)) - { - g_fWeOwnProcess = TRUE; - result = EnsureEEStarted(COINITEE_MAIN); - } - - if (FAILED(result)) - { - g_fWeOwnProcess = FALSE; - GCX_PREEMP(); - VMDumpCOMErrors(result); - SetLatchedExitCode (-1); - goto exit; - } - - INSTALL_UNWIND_AND_CONTINUE_HANDLER; - - // This will be called from a EXE so this is a self referential file so I am going to call - // ExecuteEXE which will do the work to make a EXE load. - - BOOL bretval = 0; - - bretval = ExecuteEXE(WszGetModuleHandle(NULL)); - if (!bretval) { - // The only reason I've seen this type of error in the wild is bad - // metadata file format versions and inadequate error handling for - // partially signed assemblies. While this may happen during - // development, our customers should not get here. This is a back-stop - // to catch CLR bugs. If you see this, please try to find a better way - // to handle your error, like throwing an unhandled exception. - EEMessageBoxCatastrophic(IDS_EE_COREXEMAIN_FAILED_TEXT, IDS_EE_COREXEMAIN_FAILED_TITLE); - SetLatchedExitCode (-1); - } - - UNINSTALL_UNWIND_AND_CONTINUE_HANDLER; - -exit: - STRESS_LOG1(LF_STARTUP, LL_ALWAYS, "Program exiting: return code = %d", GetLatchedExitCode()); - - STRESS_LOG0(LF_STARTUP, LL_INFO10, "EEShutDown invoked from _CorExeMainInternal"); - - EEPolicy::HandleExitProcess(); - - END_ENTRYPOINT_THROWS; - - return 0; -} - - -static BOOL CacheCommandLine(__in LPWSTR pCmdLine, __in_opt LPWSTR* ArgvW) -{ - CONTRACTL { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - PRECONDITION(CheckPointer(pCmdLine)); - PRECONDITION(CheckPointer(ArgvW)); - } CONTRACTL_END; - - if (pCmdLine) { - size_t len = wcslen(pCmdLine); - - _ASSERT(g_pCachedCommandLine== NULL); - g_pCachedCommandLine = new WCHAR[len+1]; - wcscpy_s(g_pCachedCommandLine, len+1, pCmdLine); - } - - if (ArgvW != NULL && ArgvW[0] != NULL) { - PathString wszModuleName; - PathString wszCurDir; - if (!WszGetCurrentDirectory(wszCurDir)) - return FALSE; - -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:25025) -#endif - - // usage of PathCombine is safe if we ensure that buffer specified by - // parameter1 can accomodate buffers specified by paramater2, parameter3 - // and one path separator - COUNT_T wszModuleName_len = wszCurDir.GetCount() + lstrlenW(ArgvW[0]); - WCHAR* wszModuleName_buf = wszModuleName.OpenUnicodeBuffer(wszModuleName_len); - - if (PathCombine(wszModuleName_buf, wszCurDir, ArgvW[0]) == NULL) - return FALSE; - wszModuleName.CloseBuffer(); -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - - size_t len = wszModuleName.GetCount(); - _ASSERT(g_pCachedModuleFileName== NULL); - g_pCachedModuleFileName = new WCHAR[len+1]; - wcscpy_s(g_pCachedModuleFileName, len+1, wszModuleName); - } - - return TRUE; -} - -//***************************************************************************** -// This entry point is called from the native entry point of the loaded -// executable image. The command line arguments and other entry point data -// will be gathered here. The entry point for the user image will be found -// and handled accordingly. -//***************************************************************************** -__int32 STDMETHODCALLTYPE _CorExeMain2( // Executable exit code. - PBYTE pUnmappedPE, // -> memory mapped code - DWORD cUnmappedPE, // Size of memory mapped code - __in LPWSTR pImageNameIn, // -> Executable Name - __in LPWSTR pLoadersFileName, // -> Loaders Name - __in LPWSTR pCmdLine) // -> Command Line -{ - - // This entry point is used by clix - BOOL bRetVal = 0; - - BEGIN_ENTRYPOINT_VOIDRET; - { - // Before we initialize the EE, make sure we've snooped for all EE-specific - // command line arguments that might guide our startup. - HRESULT result = CorCommandLine::SetArgvW(pCmdLine); - - if (!CacheCommandLine(pCmdLine, CorCommandLine::GetArgvW(NULL))) { - LOG((LF_STARTUP, LL_INFO10, "Program exiting - CacheCommandLine failed\n")); - bRetVal = -1; - goto exit; - } - - if (SUCCEEDED(result)) - result = InitializeEE(COINITEE_MAIN); - - if (FAILED(result)) { - VMDumpCOMErrors(result); - SetLatchedExitCode (-1); - goto exit; - } - - // Load the executable - bRetVal = ExecuteEXE(pImageNameIn); - - if (!bRetVal) { - // The only reason I've seen this type of error in the wild is bad - // metadata file format versions and inadequate error handling for - // partially signed assemblies. While this may happen during - // development, our customers should not get here. This is a back-stop - // to catch CLR bugs. If you see this, please try to find a better way - // to handle your error, like throwing an unhandled exception. - EEMessageBoxCatastrophic(IDS_EE_COREXEMAIN2_FAILED_TEXT, IDS_EE_COREXEMAIN2_FAILED_TITLE); - SetLatchedExitCode (-1); - } - -exit: - STRESS_LOG1(LF_STARTUP, LL_ALWAYS, "Program exiting: return code = %d", GetLatchedExitCode()); - - STRESS_LOG0(LF_STARTUP, LL_INFO10, "EEShutDown invoked from _CorExeMain2"); - - EEPolicy::HandleExitProcess(); - } - END_ENTRYPOINT_VOIDRET; - - return bRetVal; -} - -//***************************************************************************** -// This is the call point to wire up an EXE. In this case we have the HMODULE -// and just need to make sure we do to correct self referantial things. -//***************************************************************************** - - -BOOL STDMETHODCALLTYPE ExecuteEXE(HMODULE hMod) -{ - STATIC_CONTRACT_GC_TRIGGERS; - - _ASSERTE(hMod); - if (!hMod) - return FALSE; - - ETWFireEvent(ExecExe_V1); - - struct Param - { - HMODULE hMod; - } param; - param.hMod = hMod; - - EX_TRY_NOCATCH(Param *, pParam, ¶m) - { - // Executables are part of the system domain - SystemDomain::ExecuteMainMethod(pParam->hMod); - } - EX_END_NOCATCH; - - ETWFireEvent(ExecExeEnd_V1); - - return TRUE; -} - -BOOL STDMETHODCALLTYPE ExecuteEXE(__in LPWSTR pImageNameIn) -{ - STATIC_CONTRACT_GC_TRIGGERS; - - EX_TRY_NOCATCH(LPWSTR, pImageNameInner, pImageNameIn) - { - WCHAR wzPath[MAX_LONGPATH]; - DWORD dwPathLength = 0; - - // get the path of executable - dwPathLength = WszGetFullPathName(pImageNameInner, MAX_LONGPATH, wzPath, NULL); - - if (!dwPathLength || dwPathLength > MAX_LONGPATH) - { - ThrowWin32( !dwPathLength ? GetLastError() : ERROR_FILENAME_EXCED_RANGE); - } - - SystemDomain::ExecuteMainMethod( NULL, (WCHAR *)wzPath ); - } - EX_END_NOCATCH; - - return TRUE; -} -#endif // FEATURE_CORECLR - -#ifdef FEATURE_MIXEDMODE - -LONG RunDllMainFilter(EXCEPTION_POINTERS* ep, LPVOID pv) -{ - CONTRACTL - { - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - BOOL useLastThrownObject = UpdateCurrentThrowable(ep->ExceptionRecord); - DefaultCatchHandler(ep, NULL, useLastThrownObject, FALSE); - - DefaultCatchFilterParam param(COMPLUS_EXCEPTION_EXECUTE_HANDLER); - return DefaultCatchFilter(ep, ¶m); -} - -// <TODO>@Todo: For M10, this only runs unmanaged native classic entry points for -// the IJW mc++ case.</TODO> -HRESULT RunDllMain(MethodDesc *pMD, HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved) -{ - STATIC_CONTRACT_NOTHROW; - - _ASSERTE(!GetAppDomain()->IsPassiveDomain()); - - if (!pMD) { - _ASSERTE(!"Must have a valid function to call!"); - return E_INVALIDARG; - } - - if (pMD->IsIntrospectionOnly()) - return S_OK; - - struct Param - { - MethodDesc *pMD; - HINSTANCE hInst; - DWORD dwReason; - LPVOID lpReserved; - HRESULT hr; - }; Param param; - param.pMD = pMD; - param.hInst = hInst; - param.dwReason = dwReason; - param.lpReserved = lpReserved; - param.hr = S_OK; - - PAL_TRY(Param *, pParamOuter, ¶m) - { - EX_TRY_NOCATCH(Param *, pParam, pParamOuter) - { - HRESULT hr; - - // This call is inherently unverifiable entry point. - if (!Security::CanSkipVerification(pParam->pMD)) { - hr = SECURITY_E_UNVERIFIABLE; - goto Done; - } - - { - SigPointer sig(pParam->pMD->GetSigPointer()); - - ULONG data = 0; - CorElementType eType = ELEMENT_TYPE_END; - CorElementType eType2 = ELEMENT_TYPE_END; - - IfFailGoto(sig.GetData(&data), Done); - if (data != IMAGE_CEE_CS_CALLCONV_DEFAULT) { - hr = COR_E_METHODACCESS; - goto Done; - } - - IfFailGoto(sig.GetData(&data), Done); - if (data != 3) { - hr = COR_E_METHODACCESS; - goto Done; - } - - IfFailGoto(sig.GetElemType(&eType), Done); - if (eType != ELEMENT_TYPE_I4) { // return type = int32 - hr = COR_E_METHODACCESS; - goto Done; - } - - IfFailGoto(sig.GetElemType(&eType), Done); - if (eType == ELEMENT_TYPE_PTR) - IfFailGoto(sig.GetElemType(&eType2), Done); - - if (eType!= ELEMENT_TYPE_PTR || eType2 != ELEMENT_TYPE_VOID) { // arg1 = void* - hr = COR_E_METHODACCESS; - goto Done; - } - - IfFailGoto(sig.GetElemType(&eType), Done); - if (eType != ELEMENT_TYPE_U4) { // arg2 = uint32 - hr = COR_E_METHODACCESS; - goto Done; - } - - IfFailGoto(sig.GetElemType(&eType), Done); - if (eType == ELEMENT_TYPE_PTR) - IfFailGoto(sig.GetElemType(&eType2), Done); - - if (eType != ELEMENT_TYPE_PTR || eType2 != ELEMENT_TYPE_VOID) { // arg3 = void* - hr = COR_E_METHODACCESS; - goto Done; - } - } - - { - MethodDescCallSite dllMain(pParam->pMD); - - // Set up a callstack with the values from the OS in the argument array - ARG_SLOT stackVar[3]; - stackVar[0] = PtrToArgSlot(pParam->hInst); - stackVar[1] = (ARG_SLOT) pParam->dwReason; - stackVar[2] = PtrToArgSlot(pParam->lpReserved); - - // Call the method in question with the arguments. - if((dllMain.Call_RetI4(&stackVar[0]) == 0) - &&(pParam->dwReason==DLL_PROCESS_ATTACH) - && (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_IgnoreDllMainReturn) != 1)) - { - hr = COR_E_INVALIDPROGRAM; -#ifdef MDA_SUPPORTED - MdaDllMainReturnsFalse* pProbe = MDA_GET_ASSISTANT(DllMainReturnsFalse); - if(pProbe != NULL) pProbe->ReportError(); -#endif - } - } -Done: - pParam->hr = hr; - } - EX_END_NOCATCH - } - //@TODO: Revisit why this is here, and if it's still necessary. - PAL_EXCEPT_FILTER(RunDllMainFilter) - { - // switch to COOPERATIVE - GCX_COOP_NO_DTOR(); - // don't do anything - just want to catch it - } - PAL_ENDTRY - - return param.hr; -} - -//***************************************************************************** -// fFromThunk indicates that a dependency is calling through the Import Export table, -// and calling indirect through the IJW vtfixup slot. -// -// fFromThunk=FALSE means that we are running DllMain during LoadLibrary while -// holding the loader lock. -// -HRESULT ExecuteDLLForAttach(HINSTANCE hInst, - DWORD dwReason, - LPVOID lpReserved, - BOOL fFromThunk) -{ - CONTRACTL{ - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(CheckPointer(lpReserved, NULL_OK)); - } CONTRACTL_END; - - PEDecoder pe(hInst); - - // Note that ILOnly DLLs can have a managed entry point. This will - // be called when the assembly is activated by the CLR loader, - // and it need not be run here. - - if (pe.IsILOnly()) - { - _ASSERTE(!fFromThunk); - return S_OK; - } - - if (!pe.HasManagedEntryPoint() && !fFromThunk) - return S_OK; - - // We need to prep the managed assembly for execution. - - AppDomain *pDomain = GetAppDomain(); - - // First we must find the DomainFile associated with this HMODULE. There are basically 3 - // interesting cases: - // - // 1. The file is being loaded. In this case we have a DomainFile in existence but - // (very inconveniently) it does not have its HMODULE set yet. Most likely if we - // were to look at the state of this thread up the stack, we'd see that file is - // currently being loaded right above us. However, we cannot rely on this because - // A. We may be in case 2 (e.g. a static DLL dependency is being loaded first) - // B. _CorDllMain may have been called on a different thread. - // - // 2. The file has never been seen before. In this case we are basically in the dark; we - // simply attempt to load the file as an assembly. (If it is not an assembly we will - // fail.) - // - // 3. The file has been loaded but we are getting called anyway in a race. (This should not - // happen in the loader lock case, only when we are getting called from thunks). - // - // So, we: - // A. Use the current thread's LoadingFile as a hint. We will rely on this only if it has - // the same path as the HMOD. - // B. Search the app domain for a DomainFile with a matching base address, or failing that, path. - // C. We have no information, so assume it is a new assembly being loaded. - - // A: check the loading file - - StackSString path; - PEImage::GetPathFromDll(hInst, path); - - DomainFile *pLoadingFile = GetThread()->GetLoadingFile(); - GetThread()->ClearLoadingFile(); - - if (pLoadingFile != NULL) - { - if (!PEImage::PathEquals(pLoadingFile->GetFile()->GetPath(), path)) - { - pLoadingFile = NULL; - } - else - { - pLoadingFile->GetFile()->SetLoadedHMODULE(hInst); - } - } - - // B: look for a loading IJW module - - if (pLoadingFile == NULL) - { - pLoadingFile = pDomain->FindIJWDomainFile(hInst, path); - } - - // C: nothing else worked, we require it is an assembly with a manifest in this situation - if (pLoadingFile == NULL) - { - pLoadingFile = pDomain->LoadExplicitAssembly(hInst, FALSE)->GetDomainAssembly(); - } - - // There are two cases here, loading from thunks emitted from the shim, and being called - // inside the loader lock for the legacy IJW dll case. - - if (fFromThunk) - { - pLoadingFile->EnsureActive(); - return S_OK; - } - - _ASSERTE(!pe.IsILOnly() && pe.HasManagedEntryPoint()); - // Get the entry point for the IJW module - Module *pModule = pLoadingFile->GetCurrentModule(); - mdMethodDef tkEntry = pModule->GetEntryPointToken(); - - BOOL hasEntryPoint = (TypeFromToken(tkEntry) == mdtMethodDef && - !IsNilToken(tkEntry)); - - if (!hasEntryPoint) - { - return S_OK; - } - - if (pDomain->IsPassiveDomain()) - { - // Running managed code while holding the loader lock can cause deadlocks. - // These deadlocks might happen when this assembly gets executed. However, - // we should avoid those deadlocks if we are in a passive AppDomain. - // Also, managed entry point is now legacy, and has should be replaced - // with Module .cctor. - // - // We also rely on Module::CanExecuteCode() to prevent - // any further code from being executed from this assembly. - _ASSERTE(pLoadingFile && pLoadingFile->GetFile() && pLoadingFile->GetFile()->GetILimage()); - pLoadingFile->GetFile()->GetILimage()->SetPassiveDomainOnly(); - return S_OK; - } - - // We're actually going to run some managed code and we're inside the loader lock. - // There may be a customer debug probe enabled that prevents this. - CanRunManagedCode(hInst); - - // If we are not being called from thunks, we are inside the loader lock - // & have this single opportunity to run our dll main. - // Since we are in deadlock danger anyway (note this is the problematic legacy - // case only!) we disable our file loading and type loading reentrancy protection & allow - // loads to fully proceed. - - // class level override is needed for the entire operation, not just EnsureActive - OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOADED); - - { - OVERRIDE_LOAD_LEVEL_LIMIT(FILE_ACTIVE); - - // Complete the load as necessary - pLoadingFile->EnsureActive(); - } - - MethodDesc *pMD = pModule->FindMethodThrowing(tkEntry); - CONSISTENCY_CHECK(CheckPointer(pMD)); - - pModule->SetDllEntryPoint(pMD); - - GCX_COOP(); - - // pModule may be for a different domain. - PEFile *pPEFile = pMD->GetModule()->GetFile(); - if (!pPEFile->CheckLoaded()) - { - pPEFile->SetLoadedHMODULE(hInst); - } - - // Call the managed entry point - HRESULT hr = RunDllMain(pMD, hInst, dwReason, lpReserved); - - return hr; -} - -#endif // FEATURE_MIXEDMODE - //***************************************************************************** BOOL ExecuteDLL_ReturnOrThrow(HRESULT hr, BOOL fFromThunk) { @@ -3449,252 +2449,6 @@ BOOL ExecuteDLL_ReturnOrThrow(HRESULT hr, BOOL fFromThunk) return SUCCEEDED(hr); } -#if !defined(FEATURE_CORECLR) && defined(_DEBUG) -//***************************************************************************** -// Factor some common debug code. -//***************************************************************************** -static void EnsureManagedThreadExistsForHostedThread() -{ - CONTRACTL { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - if (CLRTaskHosted()) { - // If CLR is hosted, and this is on a thread that a host controls, - // we must have created Thread object. -#ifdef FEATURE_INCLUDE_ALL_INTERFACES - IHostTask *pHostTask = GetCurrentHostTask(); - if (pHostTask) - { - CONSISTENCY_CHECK(CheckPointer(GetThread())); - } -#endif // FEATURE_INCLUDE_ALL_INTERFACES - } -} -#endif // !FEATURE_CORECLR && _DEBUG - -#ifdef FEATURE_MIXEDMODE -//***************************************************************************** -// This ensure that the runtime is started and an EEThread object is created -// for the current thread. This functionality is duplicated in ExecuteDLL, -// except that this code will not throw. -//***************************************************************************** -HRESULT PrepareExecuteDLLForThunk(HINSTANCE hInst, - DWORD dwReason, - LPVOID lpReserved) -{ - CONTRACTL { - NOTHROW; - WRAPPER(GC_TRIGGERS); - MODE_ANY; - PRECONDITION(CheckPointer(lpReserved, NULL_OK)); - PRECONDITION(CheckPointer(hInst)); - } CONTRACTL_END; - - - HRESULT hr = S_OK; - Thread *pThread = GetThread(); - - INDEBUG(EnsureManagedThreadExistsForHostedThread();) - - if (pThread == NULL) - { - // If necessary, start the runtime and create a managed thread object. - hr = EnsureEEStarted(COINITEE_DLL); - if (FAILED(hr)) - { - return hr; - } - if ((pThread = SetupThreadNoThrow(&hr)) == NULL) - { - return hr; - } - } - - CONSISTENCY_CHECK(CheckPointer(pThread)); - - return S_OK; -} - -#endif // FEATURE_MIXEDMODE - -#ifndef FEATURE_CORECLR -//***************************************************************************** -// This is the call point to make a DLL that is already loaded into our address -// space run. There will be other code to actually have us load a DLL due to a -// class reference. -//***************************************************************************** -BOOL STDMETHODCALLTYPE ExecuteDLL(HINSTANCE hInst, - DWORD dwReason, - LPVOID lpReserved, - BOOL fFromThunk) -{ - - CONTRACTL{ - THROWS; - WRAPPER(GC_TRIGGERS); - MODE_ANY; - ENTRY_POINT; - PRECONDITION(CheckPointer(lpReserved, NULL_OK)); - PRECONDITION(CheckPointer(hInst)); - PRECONDITION(GetThread() != NULL || !fFromThunk); - } CONTRACTL_END; - - HRESULT hr = S_OK; - BOOL fRetValue = FALSE; - - // This needs to be before the BEGIN_ENTRYPOINT_THROWS since - // we can't call ReportStackOverflow if we're almost done with - // shutdown and can't run managed code. - if (!CanRunManagedCode(LoaderLockCheck::None)) - { - return fRetValue; - } - - BEGIN_ENTRYPOINT_THROWS; - - Thread *pThread = GetThread(); - - if (!hInst) - { - fRetValue = ExecuteDLL_ReturnOrThrow(E_FAIL, fFromThunk); - goto Exit; - } - - // Note that we always check fFromThunk before checking the dwReason value. - // This is because the dwReason value is undefined in the case that we're - // being invoked due to a bootstrap (because that is by definition outside - // of the loader lock and there is no appropriate dwReason value). - if (fFromThunk || - dwReason == DLL_PROCESS_ATTACH || - dwReason == DLL_THREAD_ATTACH) - { - INDEBUG(EnsureManagedThreadExistsForHostedThread();) - - - // If necessary, start the runtime and create a managed thread object. - if (fFromThunk || dwReason == DLL_PROCESS_ATTACH) - { - hr = EnsureEEStarted(COINITEE_DLL); - - if (SUCCEEDED(hr) && pThread == NULL) - { - pThread = SetupThreadNoThrow(&hr); - } - - if(FAILED(hr)) - { - fRetValue = ExecuteDLL_ReturnOrThrow(hr, fFromThunk); - goto Exit; - } - } - - // IJW assemblies cause the thread doing the process attach to - // re-enter ExecuteDLL and do a thread attach. This happens when - // CoInitializeEE() above executed - else if (!(pThread && - pThread->GetDomain() && - CanRunManagedCode(LoaderLockCheck::None))) - { - fRetValue = ExecuteDLL_ReturnOrThrow(S_OK, fFromThunk); - goto Exit; - } - - // we now have a thread setup - either the 1st if set it up, or - // the else if ran if we didn't have a thread setup. - -#ifdef FEATURE_MIXEDMODE - - EX_TRY - { - hr = ExecuteDLLForAttach(hInst, dwReason, lpReserved, fFromThunk); - } - EX_CATCH - { - // We rethrow directly here instead of using ExecuteDLL_ReturnOrThrow() to - // preserve the full exception information, rather than just the HRESULT - if (fFromThunk) - { - EX_RETHROW; - } - else - { - hr = GET_EXCEPTION()->GetHR(); - } - } - EX_END_CATCH(SwallowAllExceptions); - - if (FAILED(hr)) - { - fRetValue = ExecuteDLL_ReturnOrThrow(hr, fFromThunk); - goto Exit; - } -#endif // FEATURE_MIXEDMODE - } - else - { - PEDecoder pe(hInst); - if (pe.HasManagedEntryPoint()) - { - // If the EE is still intact, then run user entry points. Otherwise - // detach was handled when the app domain was stopped. - // - // Checks for the loader lock will occur within RunDllMain, if that's - FAULT_NOT_FATAL(); - if (CanRunManagedCode(LoaderLockCheck::None)) - { - hr = SystemDomain::RunDllMain(hInst, dwReason, lpReserved); - } - } - // This does need to match the attach. We will only unload dll's - // at the end and CoUninitialize will just bounce at 0. WHEN and IF we - // get around to unloading IL DLL's during execution prior to - // shutdown we will need to bump the reference one to compensate - // for this call. - if (dwReason == DLL_PROCESS_DETACH && !g_fForbidEnterEE) - { -#ifdef FEATURE_MIXEDMODE - // If we're in a decent state, we need to free the memory associated - // with the IJW thunk fixups. - // we are not in a decent state if the process is terminating (lpReserved!=NULL) - if (g_fEEStarted && !g_fEEShutDown && !lpReserved) - { - PEImage::UnloadIJWModule(hInst); - } -#endif // FEATURE_MIXEDMODE - } - } - - fRetValue = ExecuteDLL_ReturnOrThrow(hr, fFromThunk); - -Exit: - - END_ENTRYPOINT_THROWS; - return fRetValue; -} -#endif // !FEATURE_CORECLR - - -Volatile<BOOL> g_bIsGarbageCollectorFullyInitialized = FALSE; - -void SetGarbageCollectorFullyInitialized() -{ - LIMITED_METHOD_CONTRACT; - - g_bIsGarbageCollectorFullyInitialized = TRUE; -} - -// Tells whether the garbage collector is fully initialized -// Stronger than IsGCHeapInitialized -BOOL IsGarbageCollectorFullyInitialized() -{ - LIMITED_METHOD_CONTRACT; - - return g_bIsGarbageCollectorFullyInitialized; -} - // // Initialize the Garbage Collector // @@ -3729,19 +2483,24 @@ void InitializeGarbageCollector() IGCToCLR* gcToClr = nullptr; #endif - IGCHeap *pGCHeap = InitializeGarbageCollector(gcToClr); - g_pGCHeap = pGCHeap; - if (!pGCHeap) - ThrowOutOfMemory(); + IGCHandleTable *pGcHandleTable; - hr = pGCHeap->Initialize(); - IfFailThrow(hr); + IGCHeap *pGCHeap; + if (!InitializeGarbageCollector(gcToClr, &pGCHeap, &pGcHandleTable, &g_gc_dac_vars)) + { + ThrowOutOfMemory(); + } - // Thread for running finalizers... - FinalizerThread::FinalizerThreadCreate(); + assert(pGCHeap != nullptr); + g_pGCHeap = pGCHeap; + g_pGCHandleTable = pGcHandleTable; + g_gcDacGlobals = &g_gc_dac_vars; - // Now we really have fully initialized the garbage collector - SetGarbageCollectorFullyInitialized(); + // Apparently the Windows linker removes global variables if they are never + // read from, which is a problem for g_gcDacGlobals since it's expected that + // only the DAC will read from it. This forces the linker to include + // g_gcDacGlobals. + volatile void* _dummy = g_gcDacGlobals; } /*****************************************************************************/ @@ -3803,15 +2562,6 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. // Remember module instance g_pMSCorEE = pParam->hInst; -#ifndef FEATURE_CORECLR - CoreClrCallbacks cccallbacks; - cccallbacks.m_hmodCoreCLR = (HINSTANCE)g_pMSCorEE; - cccallbacks.m_pfnIEE = IEE; - cccallbacks.m_pfnGetCORSystemDirectory = GetCORSystemDirectoryInternaL; - cccallbacks.m_pfnGetCLRFunction = GetCLRFunction; - - InitUtilcode(cccallbacks); -#endif // !FEATURE_CORECLR // Set callbacks so that LoadStringRC knows which language our // threads are in so that it can return the proper localized string. @@ -3920,139 +2670,11 @@ BOOL STDMETHODCALLTYPE EEDllMain( // TRUE on success, FALSE on error. if (dwReason == DLL_THREAD_DETACH || dwReason == DLL_PROCESS_DETACH) { - if (CLRMemoryHosted()) - { - // A host may not support memory operation inside OS loader lock. - // We will free these memory on finalizer thread. - CExecutionEngine::DetachTlsInfo(param.pTlsData); - } - else - { - CExecutionEngine::ThreadDetaching(param.pTlsData); - } + CExecutionEngine::ThreadDetaching(param.pTlsData); } return TRUE; } -#ifdef FEATURE_COMINTEROP_REGISTRATION -//***************************************************************************** -// Helper function to call the managed registration services. -//***************************************************************************** -enum EnumRegServicesMethods -{ - RegServicesMethods_RegisterAssembly = 0, - RegServicesMethods_UnregisterAssembly, - RegServicesMethods_LastMember -}; - -void InvokeRegServicesMethod(EnumRegServicesMethods Method, HMODULE hMod) -{ - CONTRACT_VOID - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - PRECONDITION(Method == RegServicesMethods_RegisterAssembly || - Method == RegServicesMethods_UnregisterAssembly); - } - CONTRACT_END; - - GCX_PREEMP(); - Assembly *pAssembly = GetAppDomain()->LoadExplicitAssembly(hMod, TRUE); - - { - GCX_COOP(); - - // The names of the RegistrationServices methods. - static const BinderMethodID aMethods[] = - { - METHOD__REGISTRATION_SERVICES__REGISTER_ASSEMBLY, - METHOD__REGISTRATION_SERVICES__UNREGISTER_ASSEMBLY - }; - - // Allocate the RegistrationServices object. - OBJECTREF RegServicesObj = AllocateObject(MscorlibBinder::GetClass(CLASS__REGISTRATION_SERVICES)); - GCPROTECT_BEGIN(RegServicesObj) - { - MethodDescCallSite registrationMethod(aMethods[Method], &RegServicesObj); - - ARG_SLOT Args[] = - { - ObjToArgSlot(RegServicesObj), - ObjToArgSlot(pAssembly->GetExposedObject()), - 0 // unused by UnregisterAssembly - }; - - registrationMethod.Call(Args); - } - GCPROTECT_END(); - } - RETURN; -} - -//***************************************************************************** -// This entry point is called to register the classes contained inside a -// COM+ assembly. -//***************************************************************************** -STDAPI EEDllRegisterServer(HMODULE hMod) -{ - - CONTRACTL{ - NOTHROW; - GC_TRIGGERS; - ENTRY_POINT; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - HRESULT hr = S_OK; - - // Start up the runtime since we are going to use managed code to actually - // do the registration. - IfFailGo(EnsureEEStarted(COINITEE_DEFAULT)); - - BEGIN_EXTERNAL_ENTRYPOINT(&hr) - { - InvokeRegServicesMethod(RegServicesMethods_RegisterAssembly, hMod); - } - END_EXTERNAL_ENTRYPOINT; - -ErrExit: - - - return hr; -} - -//***************************************************************************** -// This entry point is called to unregister the classes contained inside a -// COM+ assembly. -//***************************************************************************** -STDAPI EEDllUnregisterServer(HMODULE hMod) -{ - - CONTRACTL{ - NOTHROW; - GC_TRIGGERS; - MODE_PREEMPTIVE; - ENTRY_POINT; - } CONTRACTL_END; - - HRESULT hr = S_OK; - - // Start up the runtime since we are going to use managed code to actually - // do the registration. - IfFailGo(EnsureEEStarted(COINITEE_DEFAULT)); - - BEGIN_EXTERNAL_ENTRYPOINT(&hr) - { - InvokeRegServicesMethod(RegServicesMethods_UnregisterAssembly, hMod); - } - END_EXTERNAL_ENTRYPOINT; -ErrExit: - - - return hr; -} -#endif // FEATURE_COMINTEROP_REGISTRATION #ifdef FEATURE_IPCMAN extern CCLRSecurityAttributeManager s_CLRSecurityAttributeManager; @@ -4124,7 +2746,6 @@ static void InitializeDebugger(void) hr = g_pDebugInterface->Startup(); // throw on error _ASSERTE(SUCCEEDED(hr)); -#ifdef FEATURE_CORECLR // // If the debug pack is not installed, Startup will return S_FALSE // and we should cleanup and proceed without debugging support. @@ -4133,31 +2754,8 @@ static void InitializeDebugger(void) { return; } -#endif // FEATURE_CORECLR - } - -#if !defined(FEATURE_CORECLR) // simple hosting - // If there's a DebuggerThreadControl interface, then we - // need to update the DebuggerSpecialThread list. - if (CorHost::GetDebuggerThreadControl()) - { - hr = CorHost::RefreshDebuggerSpecialThreadList(); - _ASSERTE((SUCCEEDED(hr)) && (hr != S_FALSE)); - - // So we don't think this will ever fail, but just in case... - IfFailThrow(hr); } - // If there is a DebuggerThreadControl interface, then it was set before the debugger - // was initialized and we need to provide this interface now. If debugging is already - // initialized then the IDTC pointer is passed in when it is set through CorHost - IDebuggerThreadControl *pDTC = CorHost::GetDebuggerThreadControl(); - - if (pDTC != NULL) - { - g_pDebugInterface->SetIDbgThreadControl(pDTC); - } -#endif // !defined(FEATURE_CORECLR) LOG((LF_CORDB, LL_INFO10, "Left-side debugging services setup.\n")); @@ -4198,9 +2796,6 @@ static void TerminateDebugger(void) g_CORDebuggerControlFlags = DBCF_NORMAL_OPERATION; -#if !defined(FEATURE_CORECLR) // simple hosting - CorHost::CleanupDebuggerThreadControl(); -#endif // !defined(FEATURE_CORECLR) } @@ -4825,247 +3420,4 @@ void ContractRegressionCheck() #endif // ENABLE_CONTRACTS_IMPL -#ifndef FEATURE_CORECLR -//------------------------------------------------------------------------- -// CorCommandLine state and methods -//------------------------------------------------------------------------- -// Class to encapsulate Cor Command line processing - -// Statics for the CorCommandLine class -DWORD CorCommandLine::m_NumArgs = 0; -LPWSTR *CorCommandLine::m_ArgvW = 0; - -LPWSTR CorCommandLine::m_pwszAppFullName = NULL; -DWORD CorCommandLine::m_dwManifestPaths = 0; -LPWSTR *CorCommandLine::m_ppwszManifestPaths = NULL; -DWORD CorCommandLine::m_dwActivationData = 0; -LPWSTR *CorCommandLine::m_ppwszActivationData = NULL; - -#ifdef _DEBUG -LPCWSTR g_CommandLine; -#endif - -// Set argvw from command line -/* static */ -HRESULT CorCommandLine::SetArgvW(LPCWSTR lpCommandLine) -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - INJECT_FAULT(return E_OUTOFMEMORY;); - - PRECONDITION(CheckPointer(lpCommandLine)); - } - CONTRACTL_END - - HRESULT hr = S_OK; - if(!m_ArgvW) { - INDEBUG(g_CommandLine = lpCommandLine); - - InitializeLogging(); // This is so early, we may not be initialized - LOG((LF_ALWAYS, LL_INFO10, "Executing program with command line '%S'\n", lpCommandLine)); - - m_ArgvW = SegmentCommandLine(lpCommandLine, &m_NumArgs); - - if (!m_ArgvW) - return E_OUTOFMEMORY; - - // Click once specific parsing - hr = ReadClickOnceEnvVariables(); - } - - return hr; -} - -// Retrieve the command line -/* static */ -LPWSTR* CorCommandLine::GetArgvW(DWORD *pNumArgs) -{ - LIMITED_METHOD_CONTRACT; - - if (pNumArgs != 0) - *pNumArgs = m_NumArgs; - - return m_ArgvW; -} - -HRESULT CorCommandLine::ReadClickOnceEnvVariables() -{ - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - HRESULT hr = S_OK; - - BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW); - - EX_TRY - { - // Find out if this is a ClickOnce application being activated. - PathString m_pwszAppFullNameHolder; - DWORD cAppFullName = WszGetEnvironmentVariable(g_pwzClickOnceEnv_FullName, m_pwszAppFullNameHolder); - if (cAppFullName > 0) { - // get the application full name. - m_pwszAppFullName = m_pwszAppFullNameHolder.GetCopyOfUnicodeString(); - - // reset the variable now that we read it so child processes - // do not think they are a clickonce app. - WszSetEnvironmentVariable(g_pwzClickOnceEnv_FullName, NULL); - - // see if we have application manifest files. - DWORD dwManifestPaths = 0; - while (1) { - StackSString manifestFile(g_pwzClickOnceEnv_Manifest); - StackSString buf; - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(dwManifestPaths, buf.OpenUnicodeBuffer(size), size, 10); - buf.CloseBuffer(); - manifestFile.Append(buf); - SString temp; - if (WszGetEnvironmentVariable(manifestFile.GetUnicode(), temp) > 0) - dwManifestPaths++; - else - break; - } - m_ppwszManifestPaths = new LPWSTR[dwManifestPaths]; - for (DWORD i=0; i<dwManifestPaths; i++) { - StackSString manifestFile(g_pwzClickOnceEnv_Manifest); - StackSString buf; - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(i, buf.OpenUnicodeBuffer(size), size, 10); - buf.CloseBuffer(); - manifestFile.Append(buf); - PathString m_ppwszManifestPathsHolder; - DWORD cManifestPath = WszGetEnvironmentVariable(manifestFile.GetUnicode(), m_ppwszManifestPathsHolder); - if (cManifestPath > 0) { - - m_ppwszManifestPaths[i] = m_ppwszManifestPathsHolder.GetCopyOfUnicodeString(); - WszSetEnvironmentVariable(manifestFile.GetUnicode(), NULL); // reset the env. variable. - } - } - m_dwManifestPaths = dwManifestPaths; - - // see if we have activation data arguments. - DWORD dwActivationData = 0; - while (1) { - StackSString activationData(g_pwzClickOnceEnv_Parameter); - StackSString buf; - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(dwActivationData, buf.OpenUnicodeBuffer(size), size, 10); - buf.CloseBuffer(); - activationData.Append(buf); - SString temp; - if (WszGetEnvironmentVariable(activationData.GetUnicode(), temp) > 0) - dwActivationData++; - else - break; - } - m_ppwszActivationData = new LPWSTR[dwActivationData]; - for (DWORD i=0; i<dwActivationData; i++) { - StackSString activationData(g_pwzClickOnceEnv_Parameter); - StackSString buf; - COUNT_T size = buf.GetUnicodeAllocation(); - _itow_s(i, buf.OpenUnicodeBuffer(size), size, 10); - buf.CloseBuffer(); - activationData.Append(buf); - PathString m_ppwszActivationDataHolder; - DWORD cActivationData = WszGetEnvironmentVariable(activationData.GetUnicode(), m_ppwszActivationDataHolder); - if (cActivationData > 0) { - m_ppwszActivationData[i] = m_ppwszActivationDataHolder.GetCopyOfUnicodeString(); - WszSetEnvironmentVariable(activationData.GetUnicode(), NULL); // reset the env. variable. - } - } - m_dwActivationData = dwActivationData; - } - } - EX_CATCH_HRESULT(hr); - - END_SO_INTOLERANT_CODE; - - return hr; -} - -#endif // !FEATURE_CORECLR - #endif // CROSSGEN_COMPILE - - -// -// GetOSVersion - Gets the real OS version bypassing the OS compatibility shim -// Mscoree.dll resides in System32 dir and is always excluded from compat shim. -// This function calls mscoree!shim function via mscoreei ICLRRuntimeHostInternal interface -// to get the OS version. We do not do this PAL or coreclr..we direclty call the OS -// in that case. -// -BOOL GetOSVersion(LPOSVERSIONINFO lposVer) -{ -#if !defined(FEATURE_CORECLR) && !defined(CROSSGEN_COMPILE) - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - MODE_ANY; - SO_TOLERANT; - } - CONTRACTL_END; - - - //declared static to cache the version info - static OSVERSIONINFOEX osvi = {0}; - BOOL ret = TRUE; - - BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), return FALSE); - - //If not yet cached get the OS version info - if(osvi.dwMajorVersion == 0) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - ReleaseHolder<ICLRRuntimeHostInternal> pRuntimeHostInternal; - //Get the interface - HRESULT hr = g_pCLRRuntime->GetInterface(CLSID_CLRRuntimeHostInternal, - IID_ICLRRuntimeHostInternal, - &pRuntimeHostInternal); - - _ASSERT(SUCCEEDED(hr)); - - //Call mscoree!GetVersionExWrapper() through mscoreei interface method - hr = pRuntimeHostInternal->GetTrueOSVersion((LPOSVERSIONINFO)&osvi); - if(!SUCCEEDED(hr)) - { - osvi.dwMajorVersion = 0; - ret = FALSE; - goto FUNCEND; - } - } - - if(lposVer->dwOSVersionInfoSize==sizeof(OSVERSIONINFOEX)||lposVer->dwOSVersionInfoSize==sizeof(OSVERSIONINFO)) - { - //Copy the cached version info to the return memory location - memcpy(lposVer,&osvi, lposVer->dwOSVersionInfoSize); - } - else - { - //return failure if dwOSVersionInfoSize not set properly - ret = FALSE; - } - -FUNCEND: - END_SO_INTOLERANT_CODE; - - return ret; -#else -// Fix for warnings when building against WinBlue build 9444.0.130614-1739 -// warning C4996: 'GetVersionExW': was declared deprecated -// externalapis\windows\winblue\sdk\inc\sysinfoapi.h(442) -// Deprecated. Use VerifyVersionInfo* or IsWindows* macros from VersionHelpers. -#pragma warning( disable : 4996 ) - return WszGetVersionEx(lposVer); -#pragma warning( default : 4996 ) -#endif -} |