msilexit.cpp
来自「C语言库函数的原型,有用的拿去」· C++ 代码 · 共 763 行 · 第 1/2 页
CPP
763 行
return retval==NULL?-1:0;
}
#if defined (_M_CEE_MIXED)
/***
* _exit_callback() - this function is called by msvcrt at exit.
*
* Purpose:
* This function is called from msvcrt dll at process exit. This
* functio then calls all the registered __clrcall function. This
* function acts as layer between __cdecl atexit callback and __clrcal
* atexit callback.
*
* Entry:
*
* Exit:
*
*******************************************************************************/
SECURITYCRITICAL_ATTRIBUTE
extern "C" void __clrcall _exit_callback(void)
{
MANAGED_ASSERT(AppDomain::CurrentDomain->IsDefaultAppDomain(), "This function must be called in the default domain");
/*
* Note: this function is not supposed to be called from more then one
* thread at a time. Infact this is called when the program is terminating
* or the dll is being unloaded.
*
* Thus we don't need to lock anything here.
*/
/*
* Note that this function is called during appdomain unload.
* Thus there should be only one thread calling this function per
* appdomain. Thus this function does not need to be under lock.
*
* Note: verify that when domainUnload event is generated, there
* are no threads executing in this appdomain. If this is not the
* case then we will need to have lock around this function.
*/
if (__exit_list_size == 0)
{
/*
* _initatexit_m() hasn't been called yet
* Nothing to do
*/
return;
}
_CPVFV * onexitbegin_m = (_CPVFV *) DecodePointer(__onexitbegin_m);
_CPVFV * onexitend_m = (_CPVFV *) DecodePointer(__onexitend_m);
if ((onexitbegin_m != (_CPVFV *)-1) && (onexitbegin_m != NULL) && (onexitend_m != NULL)) {
_CPVFV function_to_call_m = NULL;
/* save the start and end for later comparison */
_CPVFV * onexitbegin_m_saved = onexitbegin_m;
_CPVFV * onexitend_m_saved = onexitend_m;
while (1)
{
_CPVFV * onexitbegin_m_new = NULL;
_CPVFV * onexitend_m_new = NULL;
/* find the last valid function pointer to call. */
while (--onexitend_m >= onexitbegin_m && *onexitend_m == _encoded_null())
{
/* keep going backwards. */
}
if (onexitend_m < onexitbegin_m)
{
/* there are no more valid entries in the list, we are done. */
break;
}
/* cache the function to call. */
function_to_call_m = (_CPVFV) DecodePointer(*onexitend_m);
/* mark the function pointer as visited. */
*onexitend_m = (_CPVFV)_encoded_null();
/* call the function, which can eventually change __onexitbegin_m and __obexitend_m */
(*function_to_call_m)();
/* save the start and end for later comparison */
onexitbegin_m_new = (_CPVFV *) DecodePointer(__onexitbegin_m);
onexitend_m_new = (_CPVFV *) DecodePointer(__onexitend_m);
if ( ( onexitbegin_m_saved != onexitbegin_m_new ) || ( onexitend_m_saved != onexitend_m_new ) )
{
/* reset only if either start or end has changed */
onexitbegin_m = onexitbegin_m_saved = onexitbegin_m_new;
onexitend_m = onexitend_m_saved = onexitend_m_new;
}
}
/*
* There is no real need to free memory here as the process is anyway
* going down and CRT will free it's heap and this memory will anyway
* be freed. But just so that user doesn't see the memory leak if he
* wants to detect leak using CRT functionality, we free this memory.
*/
System::Runtime::InteropServices::Marshal::FreeHGlobal(
System::IntPtr((void *)onexitbegin_m));
}
__dealloc_global_lock();
}
/***
*_initatexit_m(). Initializes the managed process exit variables.
*
* Purpose:
* The _initatexit_m function is called from cctor of mixdll. This function
* is responsible for initializing managed process exit variables. The
* initialization includes allocating memory.
*
* Entry:
*
* Exit:
* 1 if initialization was sucessful 0 otherwise.
*
*******************************************************************************/
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
extern "C" int __clrcall _initatexit_m()
{
MANAGED_ASSERT(AppDomain::CurrentDomain->IsDefaultAppDomain(), "This function must be called in the default domain");
int retval = 0;
/*
* Note: This function is called only once just during cctor call.
*/
if (__alloc_global_lock() == true) {
System::IntPtr tmp_int_ptr =
System::Runtime::InteropServices::Marshal::AllocHGlobal(
32*sizeof(*__onexitbegin_m));
__onexitend_m = __onexitbegin_m = (_CPVFV *) EncodePointer(tmp_int_ptr.ToPointer());
__exit_list_size = 32;
retval = 1;
}
return retval;
}
/***
* _atexit_m(_CPVFV). registers function to be called during process exit.
*
* Purpose:
* This function registers __clrcall function to be called at processexit.
* The callback are in LIFO, i.e. last call registered will be first one
* to be called at the time of exit.
*
* Entry:
* void (__clrcall *func)(void);
*
* Exit:
* return -1 if the the function was not registered. Else returns 0.
*
* Notes:
* This routine assumes that _initatexit_m was called before this function
* is called.
*
*******************************************************************************/
extern "C" _onexit_m_t __clrcall _onexit_m( _onexit_m_t _Function)
{
MANAGED_ASSERT(AppDomain::CurrentDomain->IsDefaultAppDomain(), "This function must be called in the default domain");
return _atexit_m((_CPVFV)_Function) == -1 ? NULL : _Function;
}
SECURITYCRITICAL_ATTRIBUTE
extern "C" int __clrcall _atexit_m( _CPVFV func)
{
MANAGED_ASSERT(AppDomain::CurrentDomain->IsDefaultAppDomain(), "This function must be called in the default domain");
int retval = _atexit_helper((_CPVFV) EncodePointer(func), &__exit_list_size, &__onexitend_m, &__onexitbegin_m);
return retval;
}
#endif /* defined (_M_CEE_MIXED) */
/***
*
* AppDomain Exit stuff.
*
*******************************************************************************/
/*
* Note that the initialization values are commented out.
* The reason here is that these variables are appdomain specific. And if
* we try to initialize them, unlike process variables, they will be
* dynamically initialized. This means they will be initialized by our
* initialization routine BUT we need to initialize them before we run
* our initialization code.
*
* Not initializating them here is also OK just because we can always
* intialize them in _initatexit_app_domain function
*/
_AGLOBAL _CPVFV *__onexitbegin_app_domain /*= NULL*/;
_AGLOBAL _CPVFV *__onexitend_app_domain /*= NULL*/;
_AGLOBAL size_t __exit_list_size_app_domain /*= 0*/;
/***
*_initatexit_app_domain(). Initializes the managed per appdomain exit variables.
*
* Purpose:
* The _initatexit_app_domain function is called from cctor of mixdll. This
* function is responsible for initializing managed per appdomain exit
* variables. The initialization includes allocating memory.
*
* Entry:
*
* Exit:
* 1 if initialization was sucessful 0 otherwise.
*
*******************************************************************************/
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
extern "C" int __clrcall _initatexit_app_domain()
{
if (__alloc_global_lock() == true) {
/*
* Note that this function is called from the cctor during the
* appdomain initialization. Thus there is going to be only one thread
* per process accessing this function.
*
* Thus this function does not need to be under the lock.
*/
System::IntPtr tmp_int_ptr =
System::Runtime::InteropServices::Marshal::AllocHGlobal(
32*sizeof(*__onexitbegin_app_domain));
__onexitend_app_domain = __onexitbegin_app_domain = (_CPVFV *) EncodePointer(tmp_int_ptr.ToPointer());
__exit_list_size_app_domain = 32;
#if defined (_M_CEE_PURE)
extern void __clrcall __clean_type_info_names();
_atexit_m_appdomain(__clean_type_info_names);
#endif /* defined (_M_CEE_PURE) */
}
return 1;
}
/***
* _app_exit_callback() - this function is called by cctor during appdomain exit.
*
* Purpose:
* This function is called from cctor during appdomain exit. This
* function then calls all the registered __clrcall function. This
* function acts as appdomain version of _exit_callback.
*
* Entry:
*
* Exit:
*
*******************************************************************************/
SECURITYCRITICAL_ATTRIBUTE
extern "C" void __clrcall _app_exit_callback(void)
{
/*
* Note that this function is called during appdomain unload.
* Thus there should be only one thread calling this function per
* appdomain. Thus this function does not need to be under lock.
*
* Note: verify that when domainUnload event is generated, there
* are no threads executing in this appdomain. If this is not the
* case then we will need to have lock around this function.
*/
if (__exit_list_size_app_domain == 0 )
{
/*
* _initatexit_appdomain() hasn't been called yet
* Nothing to do
*/
return;
}
_CPVFV * onexitbegin_app_domain = (_CPVFV *) DecodePointer(__onexitbegin_app_domain);
_CPVFV * onexitend_app_domain = (_CPVFV *) DecodePointer(__onexitend_app_domain);
__try
{
if ((onexitbegin_app_domain != (_CPVFV *)-1) && (onexitbegin_app_domain != NULL) && (onexitend_app_domain != NULL)) {
_CPVFV function_to_call_app_domain = NULL;
_CPVFV * onexitbegin_app_domain_saved = onexitbegin_app_domain;
_CPVFV * onexitend_app_domain_saved = onexitend_app_domain;
while (1)
{
_CPVFV * onexitbegin_app_domain_new = NULL;
_CPVFV * onexitend_app_domain_new = NULL;
/* find the last valid function pointer to call. */
while (--onexitend_app_domain >= onexitbegin_app_domain && *onexitend_app_domain == _encoded_null())
{
/* keep going backwards. */
}
if (onexitend_app_domain < onexitbegin_app_domain)
{
/* there are no more valid entries in the list, we are done. */
break;
}
/* cache the function to call. */
function_to_call_app_domain = (_CPVFV) DecodePointer(*onexitend_app_domain);
/* mark the function pointer as visited. */
*onexitend_app_domain = (_CPVFV)_encoded_null();
/* call the function, which can eventually change __onexitbegin_app_domain and __obexitend_m */
(*function_to_call_app_domain)();
onexitbegin_app_domain_new = (_CPVFV *) DecodePointer(__onexitbegin_app_domain);
onexitend_app_domain_new = (_CPVFV *) DecodePointer(__onexitend_app_domain);
if ( ( onexitbegin_app_domain_saved != onexitbegin_app_domain_new ) ||
( onexitend_app_domain_saved != onexitend_app_domain_new ) )
{
onexitbegin_app_domain = onexitbegin_app_domain_saved = onexitbegin_app_domain_new;
onexitend_app_domain = onexitend_app_domain_saved = onexitend_app_domain_new;
}
}
}
}
__finally
{
System::Runtime::InteropServices::Marshal::FreeHGlobal(
System::IntPtr((void *)onexitbegin_app_domain));
__dealloc_global_lock();
}
}
/***
* _atexit_app_domain(_CPVFV). registers function to be called during appdomain exit.
*
* Purpose:
* This function registers __clrcall function to be called at appdomain exit.
* The callback are in LIFO, i.e. last call registered will be first one
* to be called at the time of exit. This is appdomain version of _atexit_m()
*
* Entry:
* void (__clrcall *func)(void);
*
* Exit:
* return -1 if the the function was not registered. Else returns 0.
*
* Notes:
* This routine assumes that _initatexit_app_domain was called before this
* function is called.
*
*******************************************************************************/
SECURITYCRITICAL_ATTRIBUTE
extern "C" _onexit_m_t __clrcall _onexit_m_appdomain(_onexit_m_t _Function)
{
return _atexit_m_appdomain((_CPVFV)_Function) == -1 ? NULL : _Function;
}
[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
_Check_return_ extern "C" int __clrcall _atexit_m_appdomain(_CPVFV func)
{
int retval = _atexit_helper((_CPVFV) EncodePointer(func), &__exit_list_size_app_domain, &__onexitend_app_domain, &__onexitbegin_app_domain);
return retval;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?