windows-nt/Source/XPSP1/NT/com/ole32/common/cruntime/onexit.c

138 lines
3.3 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/***
*onexit.c - save function for execution on exit
*
* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines _onexit(), atexit() - save function for execution at exit
*
*Revision History:
* 06-30-89 PHG module created, based on asm version
* 03-15-90 GJF Replace _cdecl with _CALLTYPE1, added #include
* <cruntime.h> and fixed the copyright. Also,
* cleaned up the formatting a bit.
* 05-21-90 GJF Fixed compiler warning.
* 10-04-90 GJF New-style function declarators.
* 12-28-90 SRW Added casts of func for Mips C Compiler
* 01-21-91 GJF ANSI naming.
* 09-09-91 GJF Revised for C++ needs.
* 03-20-92 SKS Revamped for new initialization model
* 04-23-92 DJM POSIX support.
* 12-02-93 SKS Add __dllonexit for DLLs using CRTDLL.DLL
*
*******************************************************************************/
#include <windows.h>
#include <stdlib.h>
#include <cruntime.h>
#include <internal.h>
#include <os2dll.h>
#ifndef _CHICAGO_
extern void DbgBreakPoint();
#endif
typedef void (_CALLTYPE1 *PF)(void); /* pointer to function */
//
// Keep this really simple: just have a vector of functions to be
// called. We use a fixed length vector, since this is a special
// application
//
#define MAX_EXIT_NOTIFICATIONS 48
PF NotificationTable[MAX_EXIT_NOTIFICATIONS];
extern PF * __onexitbegin;
extern PF * __onexitend;
/*
* Define increment (in entries) for growing the _onexit/atexit table
*/
#define ONEXITTBLINCR 4
/***
*_onexit(func), atexit(func) - add function to be executed upon exit
*
*Purpose:
* The _onexit/atexit functions are passed a pointer to a function
* to be called when the program terminate normally. Successive
* calls create a register of functions that are executed last in,
* first out.
*
*Entry:
* void (*func)() - pointer to function to be executed upon exit
*
*Exit:
* onexit:
* Success - return pointer to user's function.
* Error - return NULL pointer.
* atexit:
* Success - return 0.
* Error - return non-zero value.
*
*Notes:
* This routine depends on the behavior of _initterm() in CRT0DAT.C.
* Specifically, _initterm() must not skip the address pointed to by
* its first parameter, and must also stop before the address pointed
* to by its second parameter. This is because _onexitbegin will point
* to a valid address, and _onexitend will point at an invalid address.
*
*Exceptions:
*
*******************************************************************************/
_onexit_t _CALLTYPE1 _onexit (
_onexit_t func
)
{
PF *p;
_lockexit(); /* lock the exit code */
// If the notification table hasn't been initialized, do so
if (__onexitbegin == NULL) {
__onexitbegin = __onexitend = NotificationTable;
} else if (__onexitend >= &NotificationTable[MAX_EXIT_NOTIFICATIONS]) {
// No space...
#if DBG
OutputDebugString ("(common\\cruntime\\onexit.c\\_onexit) Too many exit notifications!\n");
DebugBreak ();
#endif
return NULL;
}
//
// Put the new entry into the table and update the end-of-table
// pointer.
//
*(__onexitend++) = (PF)func;
_unlockexit();
return func;
}
int _CALLTYPE1 atexit (
PF func
)
{
return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
}