📄 mstartup.cpp
字号:
/***
*crtexe.c - Initialization for console EXE using CRT DLL
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
* This is the actual startup routine for apps linking to the CRT DLL.
* It calls the user's main routine [w]main() or [w]WinMain after
* performing C Run-Time Library initialization.
*
* With ifdefs, this source file also provides the source code for:
* wcrtexe.c the startup routine for console apps with wide chars
* crtexew.c the startup routine for Windows apps
* wcrtexew.c the startup routine for Windows apps with wide chars
*
*******************************************************************************/
#define _CPP_MSTARTUP
#using <mscorlib.dll>
#if defined (_DEBUG)
#using <system.dll>
#endif /* defined (_DEBUG) */
/*
* SPECIAL BUILD MACROS! Note that crtexe.c (and crtexew.c) is linked in with
* the client's code. It does not go into crtdll.dll! Therefore, it must be
* built under the _DLL switch (like user code) and CRTDLL must be undefined.
* The symbol SPECIAL_CRTEXE is turned on to suppress the normal CRT DLL
* definition of _fmode and _commode using __declspec(dllexport). Otherwise
* this module would not be able to refer to both the local and DLL versions
* of these two variables.
*/
#undef MRTDLL
#define SPECIAL_CRTEXE
#include <crtdefs.h>
#include <cruntime.h>
#if defined (_M_CEE_MIXED)
/* Some inline functions (like NtCurrentTeb) need to be unmanaged */
#pragma managed(push, off)
#include <oscalls.h>
#pragma managed(pop)
#else /* defined (_M_CEE_MIXED) */
#include <oscalls.h>
#endif /* defined (_M_CEE_MIXED) */
#include <internal.h>
#include <process.h>
#include <math.h>
#include <sect_attribs.h>
#include <rterr.h>
#include <conio.h>
#include <gcroot.h>
#include <vcclr.h>
#include <eh.h>
#include <time.h>
#pragma warning(disable:4483) // disable warning/error about __identifier(<string>)
extern "C" {
// Note that managed items held in these arrays are really metadata tokens
// not clrcall function pointers so it's OK for these to be _PGLOBAL.
#if defined (_M_CEE_MIXED)
#pragma const_seg(".CRTMP$XCA")
_PGLOBAL const _CRTALLOC(".CRTMP$XCA") _PVFVM __xc_mp_a[1] = { NULL };
#pragma const_seg(".CRTMP$XCZ")
_PGLOBAL const _CRTALLOC(".CRTMP$XCZ") _PVFVM __xc_mp_z[1] = { NULL };
#endif /* defined (_M_CEE_MIXED) */
#pragma const_seg(".CRTMA$XCA")
_PGLOBAL const _CRTALLOC(".CRTMA$XCA") _PVFVM __xc_ma_a[1] = { NULL };
#pragma const_seg(".CRTMA$XCZ")
_PGLOBAL const _CRTALLOC(".CRTMA$XCZ") _PVFVM __xc_ma_z[1] = { NULL };
#pragma const_seg(".CRTVT$XCA")
_PGLOBAL const _CRTALLOC(".CRTVT$XCA") _PVFVM __xi_vt_a[1] = { NULL };
#pragma const_seg(".CRTVT$XCZ")
_PGLOBAL const _CRTALLOC(".CRTVT$XCZ") _PVFVM __xi_vt_z[1] = { NULL };
#pragma const_seg() /* reset */
#pragma comment(linker, "/merge:.CRTMP=.rdata")
#pragma comment(linker, "/merge:.CRTMA=.rdata")
#pragma comment(linker, "/merge:.CRTVT=.rdata")
#pragma comment(linker, "/defaultlib:kernel32.lib")
#if defined (_M_CEE_MIXED)
extern "C" _PGLOBAL _CRTALLOC(".CRT$XIA") _PIFV __xi_a[];
extern "C" _PGLOBAL _CRTALLOC(".CRT$XIZ") _PIFV __xi_z[]; /* C initializers */
extern "C" _PGLOBAL _CRTALLOC(".CRT$XCA") _PVFV __xc_a[];
extern "C" _PGLOBAL _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[]; /* C++ initializers */
#endif /* defined (_M_CEE_MIXED) */
}
#if defined (_M_CEE_MIXED)
extern "C" int __clrcall _initatexit_m();
extern "C" void __clrcall _exit_callback(void);
#endif /* defined (_M_CEE_MIXED) */
extern "C" int __clrcall _initatexit_app_domain();
extern "C" void __clrcall _app_exit_callback();
int __clrcall _initterm_e ( _PIFV *, _PIFV *);
void __clrcall _initterm ( _PVFV *, _PVFV *);
void __clrcall _initterm_m ( const _PVFVM *, const _PVFVM *);
#if defined (_M_CEE_MIXED)
#pragma managed(push, off)
[System::Diagnostics::DebuggerStepThroughAttribute]
void * __cdecl _getFiberPtrId()
{
return ((PNT_TIB)NtCurrentTeb())->StackBase;
}
extern "C"
void __cdecl __security_init_cookie(void);
#pragma managed(pop)
#endif /* defined (_M_CEE_MIXED) */
[System::Security::Permissions::SecurityPermissionAttribute(System::Security::Permissions::SecurityAction::Assert, UnmanagedCode = true)]
static void clock_wrapper()
{
clock();
}
#include <minternal.h>
namespace __identifier("<CrtImplementationDetails>")
{
class TriBool
{
public:
enum State { False = 0, True = -1, Unknown = 2 };
private:
TriBool();
~TriBool();
};
class Progress
{
public:
enum State { NotStarted = 0, Started, Finished };
private:
Progress();
~Progress();
};
#if defined (_M_CEE_MIXED)
class AllDomains
{
public:
// The number of domains in which the module is loaded
_PGLOBAL static int Count;
};
_PGLOBAL int AllDomains::Count = 0;
class DefaultDomain
{
private:
_PGLOBAL static TriBool::State hasPerProcess;
_PGLOBAL static TriBool::State hasNative;
/*static void __cdecl DoNothing()
{
}*/
// No secret exposed; no side effect
SECURITYSAFECRITICAL_ATTRIBUTE
static HRESULT __stdcall DoNothing(void* cookie)
{
cookie;
// Execute simple managed code
System::GC::KeepAlive(System::Int32::MaxValue);
return S_OK;
}
public:
_PGLOBAL static bool Entered;
_PGLOBAL static bool InitializedNative;
_PGLOBAL static bool InitializedNativeFromCCTOR;
_PGLOBAL static bool InitializedPerProcess;
SECURITYSAFECRITICAL_ATTRIBUTE
inline static bool HasPerProcess()
{
if (hasPerProcess == TriBool::Unknown)
{
void **pBeg = (void **)(void *)__xc_mp_a;
void **pEnd = (void **)(void *)__xc_mp_z;
while (pBeg < pEnd)
{
if (*pBeg != 0)
{
hasPerProcess = TriBool::True;
return true;
}
pBeg++;
}
hasPerProcess = TriBool::False;
return false;
}
return hasPerProcess == TriBool::True;
}
SECURITYSAFECRITICAL_ATTRIBUTE
inline static bool HasNative()
{
if (hasNative == TriBool::Unknown)
{
void **pBeg = (void **)(void *)__xi_a;
void **pEnd = (void **)(void *)__xi_z;
while (pBeg < pEnd)
{
if (*pBeg != 0)
{
hasNative = TriBool::True;
return true;
}
pBeg++;
}
pBeg = (void **)(void *)__xc_a;
pEnd = (void **)(void *)__xc_z;
while (pBeg < pEnd)
{
if (*pBeg != 0)
{
hasNative = TriBool::True;
return true;
}
pBeg++;
}
hasNative = TriBool::False;
return false;
}
return hasNative == TriBool::True;
}
SECURITYSAFECRITICAL_ATTRIBUTE
inline static bool NeedsInitialization()
{
return ((HasPerProcess() && !InitializedPerProcess) || (HasNative() && !InitializedNative && (__native_startup_state == __uninitialized)));
}
inline static bool NeedsUninitialization()
{
// If the default domain has been entered then there's a chance that
// atexit has been called and we need to transition into it to uninitialize it.
return Entered;
}
SECURITYCRITICAL_ATTRIBUTE
inline static void Initialize()
{
// Trigger call to the module constructor
DoCallBackInDefaultDomain(&DoNothing, nullptr);
}
private:
DefaultDomain();
~DefaultDomain();
};
_PGLOBAL bool DefaultDomain::Entered = false;
_PGLOBAL bool DefaultDomain::InitializedNative = false;
_PGLOBAL bool DefaultDomain::InitializedNativeFromCCTOR = false;
_PGLOBAL bool DefaultDomain::InitializedPerProcess = false;
_PGLOBAL TriBool::State DefaultDomain::hasPerProcess = TriBool::Unknown;
_PGLOBAL TriBool::State DefaultDomain::hasNative = TriBool::Unknown;
#endif /* defined (_M_CEE_MIXED) */
class CurrentDomain
{
public:
_AGLOBAL static int Initialized;
_AGLOBAL static int Uninitialized;
_AGLOBAL static bool IsDefaultDomain;
_AGLOBAL static Progress::State InitializedVtables;
_AGLOBAL static Progress::State InitializedNative;
_AGLOBAL static Progress::State InitializedPerProcess;
_AGLOBAL static Progress::State InitializedPerAppDomain;
private:
CurrentDomain(); // Not instantiable
~CurrentDomain(); // Not instantiable
};
_AGLOBAL int CurrentDomain::Initialized = 0;
_AGLOBAL int CurrentDomain::Uninitialized = 0;
_AGLOBAL bool CurrentDomain::IsDefaultDomain = false;
_AGLOBAL Progress::State CurrentDomain::InitializedVtables = Progress::NotStarted;
_AGLOBAL Progress::State CurrentDomain::InitializedNative = Progress::NotStarted;
_AGLOBAL Progress::State CurrentDomain::InitializedPerProcess = Progress::NotStarted;
_AGLOBAL Progress::State CurrentDomain::InitializedPerAppDomain = Progress::NotStarted;
class LanguageSupport
{
private:
// If a non-CRT exception is thrown, this member
// holds a constant describing the current activity
gcroot<String^> ErrorMessage;
// Initializes vtables (which are per-appdomain)
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
inline void InitializeVtables()
{
ErrorMessage = L"The C++ module failed to load during vtable initialization.\n";
CurrentDomain::InitializedVtables = Progress::Started;
_initterm_m((const _PVFVM *)__xi_vt_a, (const _PVFVM *)__xi_vt_z);
CurrentDomain::InitializedVtables = Progress::Finished;
}
#if defined (_M_CEE_MIXED)
// This is a blocking call which won't return until the default app domain is initialized
SECURITYCRITICAL_ATTRIBUTE
inline void InitializeDefaultAppDomain()
{
ErrorMessage = L"The C++ module failed to load while attempting to initialize the default appdomain.\n";
DefaultDomain::Initialize();
}
// Initializes native globals
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
inline void InitializeNative()
{
MANAGED_ASSERT(CurrentDomain::IsDefaultDomain, "Native globals must be initialized in the default domain");
ErrorMessage = L"The C++ module failed to load during native initialization.\n";
__security_init_cookie();
DefaultDomain::InitializedNative = true;
using namespace _NATIVE_STARTUP_NAMESPACE;
if (!NativeDll::IsSafeForManagedCode())
{
_amsg_exit( _RT_CRT_INIT_MANAGED_CONFLICT);
}
/*
* In mixed code we make sure to initialize native globals as well.
*/
if (__native_startup_state == __initializing)
{
_amsg_exit( _RT_CRT_INIT_MANAGED_CONFLICT);
}
else if (__native_startup_state == __uninitialized)
{
CurrentDomain::InitializedNative = Progress::Started;
__native_startup_state = __initializing;
if (_initterm_e(__xi_a, __xi_z) != 0)
{
ThrowModuleLoadException(ErrorMessage);
}
_initterm(__xc_a, __xc_z);
__native_startup_state = __initialized;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -