138 lines
3.3 KiB
C
138 lines
3.3 KiB
C
/***
|
|
*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;
|
|
}
|
|
|
|
|
|
|
|
|