📄 mstartup.cpp
字号:
DefaultDomain::InitializedNativeFromCCTOR = true;
CurrentDomain::InitializedNative = Progress::Finished;
}
}
// Initializes per-process managed globals
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
inline void InitializePerProcess()
{
MANAGED_ASSERT(CurrentDomain::IsDefaultDomain, "Per-process globals must be initialized in the default domain");
ErrorMessage = L"The C++ module failed to load during process initialization.\n";
CurrentDomain::InitializedPerProcess = Progress::Started;
_initatexit_m();
_initterm_m((const _PVFVM *) __xc_mp_a, (const _PVFVM *)__xc_mp_z );
CurrentDomain::InitializedPerProcess = Progress::Finished;
DefaultDomain::InitializedPerProcess = true;
}
#endif /* defined (_M_CEE_MIXED) */
// Initializes per-appdomain managed globals
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
inline void InitializePerAppDomain()
{
ErrorMessage = L"The C++ module failed to load during appdomain initialization.\n";
CurrentDomain::InitializedPerAppDomain = Progress::Started;
_initatexit_app_domain();
_initterm_m( __xc_ma_a, __xc_ma_z );
CurrentDomain::InitializedPerAppDomain = Progress::Finished;
}
// Registers for appdomain unload event
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
inline void InitializeUninitializer()
{
ErrorMessage = L"The C++ module failed to load during registration for the unload events.\n";
EventHandler^ handler = gcnew EventHandler(&DomainUnload);
RegisterModuleUninitializer(handler);
}
// Initializes vtables and globals required for C++ language
[System::Diagnostics::DebuggerStepThroughAttribute]
[System::Runtime::ConstrainedExecution::ReliabilityContract(
System::Runtime::ConstrainedExecution::Consistency::WillNotCorruptState,
System::Runtime::ConstrainedExecution::Cer::Success)]
SECURITYCRITICAL_ATTRIBUTE
inline void _Initialize()
{
CurrentDomain::IsDefaultDomain = AppDomain::CurrentDomain->IsDefaultAppDomain();
#if defined (_M_CEE_MIXED)
if (CurrentDomain::IsDefaultDomain)
{
DefaultDomain::Entered = true;
}
#endif /* defined (_M_CEE_MIXED) */
#if defined (_M_CEE_MIXED)
void *lock_free=0;
void *fiberid=_getFiberPtrId();
int nested=false;
int done=false;
int doInitializeDefaultAppDomain=false;
System::Runtime::CompilerServices::RuntimeHelpers::PrepareConstrainedRegions();
// this make sure that __native_startup_lock is released no matter what, in line with the
// ReliabilityContract asserted above
try
{
while (!done)
{
try { }
finally
{
#if defined (_WIN64)
lock_free = (void*)Interlocked::CompareExchange((System::Int64&)__native_startup_lock, (System::Int64)fiberid, (System::Int64)0);
#else /* defined (_WIN64) */
lock_free = (void*)Interlocked::CompareExchange((System::IntPtr&)__native_startup_lock, (System::IntPtr)fiberid, (System::IntPtr)0);
#endif /* defined (_WIN64) */
if (lock_free == 0)
{
done = true;
}
else if(lock_free == fiberid)
{
nested = true;
done = true;
}
}
if (!done)
{
// Some other thread is running native startup/shutdown during a cctor/domain unload.
// Should only happen if this DLL was built using the Everett-compat loader lock fix in vcclrit.h.
// Wait for the other thread to complete init before we return
Sleep(1000);
}
}
InitializeVtables();
if (CurrentDomain::IsDefaultDomain)
{
InitializeNative();
InitializePerProcess();
}
else if(DefaultDomain::NeedsInitialization())
{
// Do not InitializeDefaultAppDomain() when holding __native_startup_lock.
// Essentially InitializeDefaulAppDomain() is a callback to the
// default appdomain. If we do the call back while holding the lock, it can
// result in a deadlock.
//
// For example:
// 1. thread1: .cctor() of a non-default appdomain calls _Initialize() and
// grabs the _native_startup_lock
// 2. thread2: .cctor() of default appdomain starts to execute and tries to grab the
// __native_startup_lock, but fails. Hence, busy waiting for lock.
// 3. thread1: (still holding the lock) and do a callback to default appdomain.
// The CLR detects that .cctor of default appdomain has started, but
// not finish. Hence block until .cctor of default app domain finishes.
// 4. deadlock.
doInitializeDefaultAppDomain = true;
}
}
finally
{
if(!nested)
{
#if defined (_WIN64)
Interlocked::Exchange((System::Int64&)__native_startup_lock, (System::Int64)0);
#else /* defined (_WIN64) */
Interlocked::Exchange((System::IntPtr&)__native_startup_lock, (System::IntPtr)0);
#endif /* defined (_WIN64) */
}
}
/*
* Note: Since this out of the lock, it is possible that we are
* doing extra calls to InitializeDefaultAppDomain().
* Since InitializeDefaultAppDomain()is just a dummy callback to force the
* .cctor() of the default appdomain to run, it is save to call
* InitalizeDefaultAppDomain() more than once
* (although we will suffer a domain transition performance penalty.)
*/
if (doInitializeDefaultAppDomain)
{
InitializeDefaultAppDomain();
}
#else /* defined (_M_CEE_MIXED) */
InitializeVtables();
#endif /* defined (_M_CEE_MIXED) */
InitializePerAppDomain();
CurrentDomain::Initialized = 1;
InitializeUninitializer();
}
// Uninitializes per-appdomain managed globals
SECURITYCRITICAL_ATTRIBUTE
inline static void UninitializeAppDomain()
{
_app_exit_callback();
}
#if defined (_M_CEE_MIXED)
//static void __cdecl _UninitializeDefaultDomain()
SECURITYCRITICAL_ATTRIBUTE
static HRESULT __stdcall _UninitializeDefaultDomain(void* cookie)
{
cookie;
MANAGED_ASSERT(AppDomain::CurrentDomain->IsDefaultAppDomain(), "This function must be called in the default domain");
// Uninitialize per-process
_exit_callback();
DefaultDomain::InitializedPerProcess = false;
if(DefaultDomain::InitializedNativeFromCCTOR)
{
// Uninitialize native
_cexit();
__native_startup_state = __uninitialized;
DefaultDomain::InitializedNativeFromCCTOR = false;
}
DefaultDomain::InitializedNative = false;
return S_OK;
}
SECURITYCRITICAL_ATTRIBUTE
static void UninitializeDefaultDomain()
{
if (DefaultDomain::NeedsUninitialization())
{
if (AppDomain::CurrentDomain->IsDefaultAppDomain())
{
_UninitializeDefaultDomain(nullptr);
}
else
{
DoCallBackInDefaultDomain(&_UninitializeDefaultDomain, nullptr);
}
}
}
#endif /* defined (_M_CEE_MIXED) */
// Called when the domain unloads
// Compare with code in Cleanup
[System::Runtime::ConstrainedExecution::PrePrepareMethod]
[System::Runtime::ConstrainedExecution::ReliabilityContract(
System::Runtime::ConstrainedExecution::Consistency::WillNotCorruptState,
System::Runtime::ConstrainedExecution::Cer::Success)]
SECURITYCRITICAL_ATTRIBUTE
static void DomainUnload(Object^ source, EventArgs^ arguments)
{
if (CurrentDomain::Initialized && !Interlocked::Exchange(CurrentDomain::Uninitialized, (int)1))
{
#if defined (_M_CEE_MIXED)
bool lastDomain = (Interlocked::Decrement(AllDomains::Count) == 0);
#endif /* defined (_M_CEE_MIXED) */
UninitializeAppDomain();
#if defined (_M_CEE_MIXED)
if (lastDomain)
{
UninitializeDefaultDomain();
}
#endif /* defined (_M_CEE_MIXED) */
}
}
// Cleans up initialization in the event of an error
// Compare with code in DomainUnload
[System::Diagnostics::DebuggerStepThroughAttribute]
[System::Runtime::ConstrainedExecution::ReliabilityContract(
System::Runtime::ConstrainedExecution::Consistency::WillNotCorruptState,
System::Runtime::ConstrainedExecution::Cer::Success)]
SECURITYCRITICAL_ATTRIBUTE
void Cleanup(System::Exception^ innerException)
{
try
{
#if defined (_M_CEE_MIXED)
// If we end up here, DomainUnload will not be called
bool lastDomain = (Interlocked::Decrement(AllDomains::Count) == 0);
#endif /* defined (_M_CEE_MIXED) */
/*
* Even though the current AppDomain might not be fully initialized,
* we still want to call whatever that got registered in the on exit
* list.
*/
UninitializeAppDomain();
#if defined (_M_CEE_MIXED)
if (lastDomain)
{
UninitializeDefaultDomain();
}
#endif /* defined (_M_CEE_MIXED) */
}
catch (System::Exception^ exception)
{
ThrowNestedModuleLoadException(innerException, exception);
}
catch (System::Object^ exception)
{
exception;
ThrowNestedModuleLoadException(innerException, nullptr);
}
}
public:
SECURITYCRITICAL_ATTRIBUTE
LanguageSupport(){}
SECURITYCRITICAL_ATTRIBUTE
~LanguageSupport(){}
[System::Diagnostics::DebuggerStepThroughAttribute]
[System::Runtime::ConstrainedExecution::ReliabilityContract(
System::Runtime::ConstrainedExecution::Consistency::WillNotCorruptState,
System::Runtime::ConstrainedExecution::Cer::Success)]
SECURITYCRITICAL_ATTRIBUTE
void Initialize()
{
#if defined (_M_CEE_MIXED)
bool allDomainsCountIncremented = false;
// this make sure that AllDomains::Count reflects the actual count no matter what,
// in line with the ReliabilityContract asserted above
System::Runtime::CompilerServices::RuntimeHelpers::PrepareConstrainedRegions();
#endif /* defined (_M_CEE_MIXED) */
try
{
ErrorMessage = L"The C++ module failed to load.\n";
#if defined (_M_CEE_MIXED)
System::Runtime::CompilerServices::RuntimeHelpers::PrepareConstrainedRegions();
try { } finally
{
Interlocked::Increment(AllDomains::Count);
allDomainsCountIncremented = true;
}
#endif /* defined (_M_CEE_MIXED) */
_Initialize();
}
catch (System::Exception^ exception)
{
#if defined (_M_CEE_MIXED)
if (allDomainsCountIncremented)
#endif /* defined (_M_CEE_MIXED) */
{
Cleanup(exception);
}
ThrowModuleLoadException(ErrorMessage, exception);
}
catch (System::Object^ exception)
{
exception;
#if defined (_M_CEE_MIXED)
if (allDomainsCountIncremented)
#endif /* defined (_M_CEE_MIXED) */
{
Cleanup(nullptr);
}
ThrowModuleLoadException(ErrorMessage, nullptr);
}
}
};
// we do lots of nasty things for /clr & /clr:pure - consuming code should
// automatically be marked for compatibility with the security model enforced in CLR v4+
[ assembly: System::Security::SecurityRules( System::Security::SecurityRuleSet::Level1 ) ];
} // namespace __identifier("<CrtImplementationDetails>")
/***
* .cctor - This is global constructor for user module.
*
* Purpose:
* This function is called during appdomain creation. Here is we
* initialize all the vtables, and native/process/appdomain variables.
*
* Exit:
*
* Entry:
*
*******************************************************************************/
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
void __clrcall __identifier(".cctor")()
{
using namespace __identifier("<CrtImplementationDetails>");
LanguageSupport languageSupport;
languageSupport.Initialize();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -