crt0dat.c
来自「C语言库函数的原型,有用的拿去」· C语言 代码 · 共 989 行 · 第 1/2 页
C
989 行
{
/*
Only if the EXE is managed then we call CorExitProcess.
Native cleanup is done in .cctor of the EXE
If the Exe is Native then native clean up should be done
before calling (Cor)ExitProcess.
*/
__crtCorExitProcess(code);
}
#endif /* CRTDLL */
_lockexit(); /* assure only 1 thread in exit path */
__TRY
if (_C_Exit_Done != TRUE) {
_C_Termination_Done = TRUE;
/* save callable exit flag (for use by terminators) */
_exitflag = (char) retcaller; /* 0 = term, !0 = callable exit */
if (!quick) {
/*
* do _onexit/atexit() terminators
* (if there are any)
*
* These terminators MUST be executed in reverse order (LIFO)!
*
* NOTE:
* This code assumes that __onexitbegin points
* to the first valid onexit() entry and that
* __onexitend points past the last valid entry.
* If __onexitbegin == __onexitend, the table
* is empty and there are no routines to call.
*/
_PVFV * onexitbegin = (_PVFV *) DecodePointer(__onexitbegin);
if (onexitbegin) {
_PVFV * onexitend = (_PVFV *) DecodePointer(__onexitend);
_PVFV function_to_call = NULL;
/* save the start and end for later comparison */
_PVFV * onexitbegin_saved = onexitbegin;
_PVFV * onexitend_saved = onexitend;
while (1)
{
_PVFV * onexitbegin_new = NULL;
_PVFV * onexitend_new = NULL;
/* find the last valid function pointer to call. */
while (--onexitend >= onexitbegin && *onexitend == _encoded_null())
{
/* keep going backwards. */
}
if (onexitend < onexitbegin)
{
/* there are no more valid entries in the list, we are done. */
break;
}
/* cache the function to call. */
function_to_call = (_PVFV) DecodePointer(*onexitend);
/* mark the function pointer as visited. */
*onexitend = (_PVFV)_encoded_null();
/* call the function, which can eventually change __onexitbegin and __onexitend */
(*function_to_call)();
onexitbegin_new = (_PVFV *) DecodePointer(__onexitbegin);
onexitend_new = (_PVFV *) DecodePointer(__onexitend);
if ( ( onexitbegin_saved != onexitbegin_new ) || ( onexitend_saved != onexitend_new ) )
{
/* reset only if either start or end has changed */
onexitbegin = onexitbegin_saved = onexitbegin_new;
onexitend = onexitend_saved = onexitend_new;
}
}
}
#ifndef CRTDLL
/*
* do pre-terminators
*/
_initterm(__xp_a, __xp_z);
#endif /* CRTDLL */
}
#ifndef CRTDLL
/*
* do terminators
*/
_initterm(__xt_a, __xt_z);
#endif /* CRTDLL */
#ifdef _DEBUG
/* Dump all memory leaks */
if (!fExit && _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF)
{
fExit = 1;
#ifndef CRTDLL
__freeCrtMemory();
_CrtDumpMemoryLeaks();
#endif /* CRTDLL */
}
#endif /* _DEBUG */
}
/* return to OS or to caller */
__FINALLY
if (retcaller)
_unlockexit(); /* unlock the exit code path */
__END_TRY_FINALLY
if (retcaller)
return;
_C_Exit_Done = TRUE;
_unlockexit(); /* unlock the exit code path */
__crtExitProcess(code);
}
#ifdef CRTDLL
/***
* __crtdll_callstaticterminators
*
*Purpose:
* call terminators. This is called from CRT_INIT when dll entrypoint is
* called with DLL_PROCESS_DETACH. We can't call the terminators from exit
* as there may be some dll that may need crt functionality during
* DLL_PROCESS_DETACH
*
*******************************************************************************/
void __crtdll_callstaticterminators(void) {
/*
* do pre-terminators
*/
_initterm(__xp_a, __xp_z);
/*
* do terminators
*/
_initterm(__xt_a, __xt_z);
}
#endif /* CRTDLL */
/***
* __crtCorExitProcess - CRT wrapper for CorExitProcess
* __crtExitProcess - CRT wrapper for ExitProcess
*
*Purpose:
* If we're part of a managed app, then call the CorExitProcess,
* otherwise call ExitProcess. For managed apps, calling ExitProcess can
* be problematic, because it doesn't give the managed FinalizerThread a
* chance to clean up.
*
* To determine if we're a managed app, we check if mscoree.dll is loaded.
* Then, if CorExitProcess is available, we call it.
*
*Entry:
* int status - exit code
*
*Exit:
* Does not return
*
*Exceptions:
*
*******************************************************************************/
typedef void (WINAPI * PFN_EXIT_PROCESS)(UINT uExitCode);
void __cdecl __crtCorExitProcess (
int status
)
{
HMODULE hmod;
PFN_EXIT_PROCESS pfn;
hmod = GetModuleHandleW(L"mscoree.dll");
if (hmod != NULL) {
pfn = (PFN_EXIT_PROCESS)GetProcAddress(hmod, "CorExitProcess");
if (pfn != NULL) {
pfn(status);
}
}
/*
* Either mscoree.dll isn't loaded,
* or CorExitProcess isn't exported from mscoree.dll,
* or CorExitProcess returned (should never happen).
* Just call return.
*/
}
void __cdecl __crtExitProcess (
int status
)
{
__crtCorExitProcess(status);
/*
* Either mscoree.dll isn't loaded,
* or CorExitProcess isn't exported from mscoree.dll,
* or CorExitProcess returned (should never happen).
* Just call ExitProcess.
*/
ExitProcess(status);
}
/***
* _lockexit - Aquire the exit code lock
*
*Purpose:
* Makes sure only one thread is in the exit code at a time.
* If a thread is already in the exit code, it must be allowed
* to continue. All other threads must pend.
*
* Notes:
*
* (1) It is legal for a thread that already has the lock to
* try and get it again(!). That is, consider the following
* sequence:
*
* (a) program calls exit()
* (b) thread locks exit code
* (c) user onexit() routine calls _exit()
* (d) same thread tries to lock exit code
*
* Since _exit() must ALWAYS be able to work (i.e., can be called
* from anywhere with no regard for locking), we must make sure the
* program does not deadlock at step (d) above.
*
* (2) If a thread executing exit() or _exit() aquires the exit lock,
* other threads trying to get the lock will pend forever. That is,
* since exit() and _exit() terminate the process, there is not need
* for them to unlock the exit code path.
*
* (3) Note that onexit()/atexit() routines call _lockexit/_unlockexit
* to protect mthread access to the onexit table.
*
* (4) The 32-bit OS semaphore calls DO allow a single thread to acquire
* the same lock multiple times* thus, this version is straight forward.
*
*Entry: <none>
*
*Exit:
* Calling thread has exit code path locked on return.
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _lockexit (
void
)
{
_mlock(_EXIT_LOCK1);
}
/***
* _unlockexit - Release exit code lock
*
*Purpose:
* [See _lockexit() description above.]
*
* This routine is called by _cexit(), _c_exit(), and onexit()/atexit().
* The exit() and _exit() routines never unlock the exit code path since
* they are terminating the process.
*
*Entry:
* Exit code path is unlocked.
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
void __cdecl _unlockexit (
void
)
{
_munlock(_EXIT_LOCK1);
}
/***
*_init_pointers() - initialize global function pointers with OS encoded values
*
*Purpose:
*
*Entry:
*
*Exit:
*
*Exceptions:
*
*******************************************************************************/
extern void __cdecl _initp_eh_hooks(void*);
extern void __cdecl _initp_heap_handler(void*);
extern void __cdecl _initp_misc_invarg(void*);
extern void __cdecl _initp_misc_purevirt(void*);
extern void __cdecl _initp_misc_rand_s(void*);
extern void __cdecl _initp_misc_winsig(void*);
void __cdecl _init_pointers() {
void *enull = _encoded_null();
_initp_heap_handler(enull);
_initp_misc_invarg(enull);
_initp_misc_purevirt(enull);
_initp_misc_rand_s(enull);
_initp_misc_winsig(enull);
_initp_eh_hooks(enull);
}
/***
* static void _initterm(_PVFV * pfbegin, _PVFV * pfend) - call entries in
* function pointer table
*
*Purpose:
* Walk a table of function pointers, calling each entry, as follows:
*
* 1. walk from beginning to end, pfunctbl is assumed to point
* to the beginning of the table, which is currently a null entry,
* as is the end entry.
* 2. skip NULL entries
* 3. stop walking when the end of the table is encountered
*
*Entry:
* _PVFV *pfbegin - pointer to the beginning of the table (first
* valid entry).
* _PVFV *pfend - pointer to the end of the table (after last
* valid entry).
*
*Exit:
* No return value
*
*Notes:
* This routine must be exported in the CRT DLL model so that the client
* EXE and client DLL(s) can call it to initialize their C++ constructors.
*
*Exceptions:
* If either pfbegin or pfend is NULL, or invalid, all bets are off!
*
*******************************************************************************/
#ifdef CRTDLL
void __cdecl _initterm (
#else /* CRTDLL */
static void __cdecl _initterm (
#endif /* CRTDLL */
_PVFV * pfbegin,
_PVFV * pfend
)
{
/*
* walk the table of function pointers from the bottom up, until
* the end is encountered. Do not skip the first entry. The initial
* value of pfbegin points to the first valid entry. Do not try to
* execute what pfend points to. Only entries before pfend are valid.
*/
while ( pfbegin < pfend )
{
/*
* if current table entry is non-NULL, call thru it.
*/
if ( *pfbegin != NULL )
(**pfbegin)();
++pfbegin;
}
}
/***
* static int _initterm_e(_PIFV * pfbegin, _PIFV * pfend) - call entries in
* function pointer table, return error code on any failure
*
*Purpose:
* Walk a table of function pointers in the same way as _initterm, but
* here the functions return an error code. If an error is returned, it
* will be a nonzero value equal to one of the _RT_* codes.
*
*Entry:
* _PIFV *pfbegin - pointer to the beginning of the table (first
* valid entry).
* _PIFV *pfend - pointer to the end of the table (after last
* valid entry).
*
*Exit:
* No return value
*
*Notes:
* This routine must be exported in the CRT DLL model so that the client
* EXE and client DLL(s) can call it.
*
*Exceptions:
* If either pfbegin or pfend is NULL, or invalid, all bets are off!
*
*******************************************************************************/
int __cdecl _initterm_e (
_PIFV * pfbegin,
_PIFV * pfend
)
{
int ret = 0;
/*
* walk the table of function pointers from the bottom up, until
* the end is encountered. Do not skip the first entry. The initial
* value of pfbegin points to the first valid entry. Do not try to
* execute what pfend points to. Only entries before pfend are valid.
*/
while ( pfbegin < pfend && ret == 0)
{
/*
* if current table entry is non-NULL, call thru it.
*/
if ( *pfbegin != NULL )
ret = (**pfbegin)();
++pfbegin;
}
return ret;
}
/***
*errno_t _get_wpgmptr() - get _wpgmptr, i.e. the module (EXE) wide name
*
*Purpose:
* Get the value of _wpgmptr
*
*Entry:
* wchar_t **pValue - pointer where to store the value
*
*Exit:
* The error code
*
*Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
errno_t _get_wpgmptr(wchar_t **pValue)
{
/* validation section */
_VALIDATE_RETURN_ERRCODE(pValue != NULL, EINVAL);
_BEGIN_SECURE_CRT_DEPRECATION_DISABLE
_VALIDATE_RETURN_ERRCODE(_wpgmptr != NULL, EINVAL);
*pValue = _wpgmptr;
_END_SECURE_CRT_DEPRECATION_DISABLE
return 0;
}
/***
*errno_t _get_pgmptr() - get _pgmptr, i.e. the module (EXE) name
*
*Purpose:
* Get the value of _pgmptr
*
*Entry:
* char **pValue - pointer where to store the value
*
*Exit:
* The error code
*
*Exceptions:
* Input parameters are validated. Refer to the validation section of the function.
*
*******************************************************************************/
errno_t _get_pgmptr(char **pValue)
{
/* validation section */
_VALIDATE_RETURN_ERRCODE(pValue != NULL, EINVAL);
_BEGIN_SECURE_CRT_DEPRECATION_DISABLE
_VALIDATE_RETURN_ERRCODE(_pgmptr != NULL, EINVAL);
*pValue = _pgmptr;
_END_SECURE_CRT_DEPRECATION_DISABLE
return 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?