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