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 + -
显示快捷键?