msilexit.cpp

来自「C语言库函数的原型,有用的拿去」· C++ 代码 · 共 763 行 · 第 1/2 页

CPP
763
字号
/***
*msilexit.cpp - Exit routines for mixdll.
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       This file provides at_exit support for clrcall functions. Here you will
*       find implementation for both managed process exit and appdomain exit.
*
*******************************************************************************/

#ifdef MRTDLL
#undef MRTDLL
#endif  /* MRTDLL */

#include <internal.h>
#include <windows.h>
#include <malloc.h>
#include <mtdll.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <gcroot.h>

#using <mscorlib.dll>
#if defined (_DEBUG)
#using <system.dll>
#endif  /* defined (_DEBUG) */

#pragma warning(disable:4439)   // C4439: function with a managed parameter must have a __clrcall calling convention
#pragma warning(disable:4483)   // disable warning/error about __identifier(<string>)

using System::AppDomain;

#if defined (_DEBUG)
    #define MANAGED_ASSERT( test, message) System::Diagnostics::Debug::Assert(test, message)
#else  /* defined (_DEBUG) */
    #define MANAGED_ASSERT( test, message )
#endif  /* defined (_DEBUG) */

/*
 * match these macros with the ones in onexit.c
 */
#define MAXINCR     512
#define MININCR     4

extern "C" {
    typedef void (__clrcall *_CPVFV)(void);
}

#if defined (_M_CEE_MIXED)
static _CPVFV *__onexitbegin_m  = NULL;
static _CPVFV *__onexitend_m = NULL;
static size_t __exit_list_size = 0;
#endif  /* defined (_M_CEE_MIXED) */

namespace __identifier("<CrtImplementationDetails>")
{
using System::Threading::Monitor;
using System::Object;
using System::Runtime::InteropServices::GCHandle;
using System::IntPtr;

class AtExitLock
{
private:
    _AGLOBAL static void* _lock;
    _AGLOBAL static int _ref_count;

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static GCHandle^ _handle()
    {
        if (_lock != nullptr)
        {
            return GCHandle::FromIntPtr(IntPtr(_lock));
        }

        return nullptr;
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    static void _lock_Construct()
    {
        _lock = 0;
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static void _lock_Construct(Object^ value)
    {
        _lock = 0;
        _lock_Set(value);
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static void _lock_Set(Object^ value)
    {
        GCHandle^ handle = _handle();
        if (handle == nullptr)
        {
            handle = GCHandle::Alloc(value);
            _lock = GCHandle::ToIntPtr(*handle).ToPointer();
        }
        else
        {
            handle->Target = value;
        }
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static Object^ _lock_Get()
    {
        GCHandle^ handle = _handle();
        if (handle != nullptr)
        {
            return (Object^)handle->Target;
        }
        return nullptr;
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static void _lock_Destruct()
    {
        GCHandle^ handle = _handle();
        if (handle != nullptr)
        {
            handle->Free();
            _lock = 0;
        }
    }

public:
    // No secret exposed; no side effect
    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYSAFECRITICAL_ATTRIBUTE
    static bool IsInitialized()
    {
        return (_lock_Get() != nullptr);
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static void AddRef()
    {
        if (!IsInitialized())
        {
            _lock_Construct(gcnew Object());
            _ref_count = 0;
        }
        ++_ref_count;
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static void RemoveRef()
    {
        MANAGED_ASSERT(_ref_count > 0, "Reference count must be greater than zero");
        if (--_ref_count == 0)
        {
            MANAGED_ASSERT(IsInitialized(), "Lock must be initialized");
            _lock_Destruct();
        }
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static void Enter()
    {
#pragma warning( push )
#pragma warning( disable : 4947 )
        //@TODO: This overload of Monitor::Enter is obsolete.  Please change this to use Monitor::Enter(bool&), and remove the pragmas   -- ericeil
        Monitor::Enter(_lock_Get());
#pragma warning( pop )
    }

    [System::Diagnostics::DebuggerStepThroughAttribute]
    SECURITYCRITICAL_ATTRIBUTE
    static void Exit()
    {
        Monitor::Exit(_lock_Get());
    }
};
_AGLOBAL void * AtExitLock::_lock; /* Do NOT initialize */
_AGLOBAL int AtExitLock::_ref_count /*= 0*/; /* Do NOT initialize */
}

/***
* __global_lock() - lock access for __global_lock_object
*
* Purpose:
*       This funciton is used by atexit funcitons to avoid parllel
*       access to critical data.
*
* Entry:
*
* Exit:
*       returns true if sucessful.
*
*******************************************************************************/

[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
static bool __global_lock()
{
    using namespace __identifier("<CrtImplementationDetails>");

    bool retval = false;
    if (AtExitLock::IsInitialized())
    {
        AtExitLock::Enter();
        retval = true;
    }
    return retval;
}

/***
* __global_unlock() - releases the lock held by calling __global_lock
*
* Purpose:
*       Release the lock held by calling __global_lock.
*
* Entry:
*
* Exit:
*       returns true if sucessful.
*
*******************************************************************************/

[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
static bool __global_unlock()
{
    using namespace __identifier("<CrtImplementationDetails>");

    bool retval = false;
    if (AtExitLock::IsInitialized())
    {
        AtExitLock::Exit();
        retval = true;
    }
    return retval;
}

/***
* __alloc_global_lock() - allocates CLR lock for access to lockClass::__global_lock_object
*
* Purpose:
*       This lock object is used by atexit routines to have single threaded
*       access to critical data.
*
* Entry:
*
* Exit:
*       return true if sucessful.
*
*******************************************************************************/

[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
static bool __alloc_global_lock()
{
    using namespace __identifier("<CrtImplementationDetails>");

    AtExitLock::AddRef();
    return AtExitLock::IsInitialized();
}

/***
* __dealloc_global_lock() - deallocates the lock used for access to lockClass::__global_lock_object
*
* Purpose:
*       Remove the reference to the lock object
*
* Entry:
*
* Exit:
*
*******************************************************************************/

[System::Diagnostics::DebuggerStepThroughAttribute]
SECURITYCRITICAL_ATTRIBUTE
static void __dealloc_global_lock()
{
    using namespace __identifier("<CrtImplementationDetails>");

    AtExitLock::RemoveRef();
}

/***
* _atexit_helper(). 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:
*       _CPVFV,
*       size_t *,
*       _CPVFV **,
*       _CPVFV **;
*
* 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.
*
*******************************************************************************/

SECURITYCRITICAL_ATTRIBUTE
extern "C" int __clrcall _atexit_helper( _CPVFV func,
        size_t *__pexit_list_size,
        _CPVFV **__ponexitend_e,
        _CPVFV **__ponexitbegin_e)
{
    _CPVFV retval = NULL;

    /*
     * Get the lock for CRT exit function calls.
     */
    if (func == NULL) return -1;
    if (__global_lock() == true) {
        try {
            _CPVFV * __onexitbegin = (_CPVFV *) DecodePointer(*__ponexitbegin_e);
            _CPVFV * __onexitend = (_CPVFV *) DecodePointer(*__ponexitend_e);

            /*
             * check if we have space of one more entry.
             */
            if ( (*__pexit_list_size) - 1<
                    ((size_t)((char *)__onexitend - (char *)__onexitbegin))/sizeof(_CPVFV))
            {
                /*
                 * Try to increment by max increment or twice the current size, if fails,
                 * then try to increment by min increment. If that too fails then return NULL.
                 */
                try {
                    System::IntPtr tmp_ptr =
                        System::Runtime::InteropServices::Marshal::ReAllocHGlobal(
                            System::IntPtr(__onexitbegin),
                            System::IntPtr((long)((*__pexit_list_size)*sizeof(_CPVFV)+
                                __min((*__pexit_list_size)*sizeof(_CPVFV),
                                    (MAXINCR*sizeof(_CPVFV))))));

                    __onexitend = (_CPVFV *)((char *)tmp_ptr.ToPointer()+
                            (size_t)__onexitend-
                            (size_t)__onexitbegin);
                    __onexitbegin = (_CPVFV *)tmp_ptr.ToPointer();
                    (*__pexit_list_size) += __min(MAXINCR, (*__pexit_list_size));

                } catch (System::OutOfMemoryException ^) {

                    System::IntPtr tmp_ptr =
                        System::Runtime::InteropServices::Marshal::ReAllocHGlobal(
                            System::IntPtr(__onexitbegin),
                            System::IntPtr((long)((*__pexit_list_size)*sizeof(_CPVFV)+
                                MININCR+sizeof(_CPVFV))));

                    __onexitend = (_CPVFV *)((char *)tmp_ptr.ToPointer()+
                            (size_t)__onexitend-
                            (size_t)__onexitbegin);
                    __onexitbegin = (_CPVFV *)tmp_ptr.ToPointer();
                    (*__pexit_list_size) += MININCR;
                }
            }
            *(__onexitend++) = (_CPVFV)func;
            retval = func;

            (*__ponexitbegin_e) = (_CPVFV *) EncodePointer(__onexitbegin);
            (*__ponexitend_e) = (_CPVFV *) EncodePointer(__onexitend);

        } catch(System::OutOfMemoryException ^) {
        } __finally{
            __global_unlock();
        }
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?