187 lines
4.9 KiB
C
187 lines
4.9 KiB
C
|
/*
|
||
|
* CRTDLL exit/abort/atexit functions
|
||
|
*
|
||
|
* Copyright 1996,1998 Marcus Meissner
|
||
|
* Copyright 1996 Jukka Iivonen
|
||
|
* Copyright 1997,2000 Uwe Bonnes
|
||
|
* Copyright 2000 Jon Griffiths
|
||
|
*
|
||
|
* exit functions differ in whether they perform cleanup
|
||
|
* and whether they return to the caller (really!).
|
||
|
* return do
|
||
|
* Name to caller? cleanup?
|
||
|
* _c_exit Y N
|
||
|
* _cexit Y Y
|
||
|
* _exit N N
|
||
|
* exit N Y
|
||
|
*
|
||
|
* Implementation Notes:
|
||
|
* Not MT Safe - Adding/Executing exit() functions should be locked
|
||
|
* for MT safety.
|
||
|
*
|
||
|
* FIXME:
|
||
|
* Need a better way of printing errors for GUI programs(MsgBox?).
|
||
|
* Is there really a difference between onexit/atexit?
|
||
|
*/
|
||
|
#include "crtdll.h"
|
||
|
#include <errno.h>
|
||
|
#include "process.h"
|
||
|
|
||
|
|
||
|
DEFAULT_DEBUG_CHANNEL(crtdll);
|
||
|
|
||
|
/* INTERNAL: Table of registered atexit() functions */
|
||
|
/* FIXME: This should be dynamically allocated */
|
||
|
#define CRTDLL_ATEXIT_TABLE_SIZE 16
|
||
|
|
||
|
static atexit_function atexit_table[CRTDLL_ATEXIT_TABLE_SIZE];
|
||
|
static int atexit_registered = 0; /* Points to free slot */
|
||
|
|
||
|
|
||
|
/* INTERNAL: call atexit functions */
|
||
|
void __CRTDLL__call_atexit(VOID);
|
||
|
void __CRTDLL__call_atexit(VOID)
|
||
|
{
|
||
|
/* Last registered gets executed first */
|
||
|
while (atexit_registered > 0)
|
||
|
{
|
||
|
atexit_registered--;
|
||
|
TRACE(":call function (%p)\n",atexit_table[atexit_registered]);
|
||
|
(*atexit_table[atexit_registered])();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* __dllonexit (CRTDLL.25)
|
||
|
*/
|
||
|
VOID __cdecl CRTDLL___dllonexit ()
|
||
|
{
|
||
|
FIXME("stub\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* _abnormal_termination (CRTDLL.36)
|
||
|
*
|
||
|
* Check if execution is processing during an exception.
|
||
|
*/
|
||
|
INT __cdecl CRTDLL__abnormal_termination(VOID)
|
||
|
{
|
||
|
TRACE("(void)\n");
|
||
|
return 0; /* FIME: Can we determine if we are in an exception? */
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* _amsg_exit (CRTDLL.040)
|
||
|
*
|
||
|
* Print an error message and terminate execution. Returns 255 to the
|
||
|
* host OS.
|
||
|
*/
|
||
|
VOID __cdecl CRTDLL__amsg_exit(INT err)
|
||
|
{
|
||
|
CRTDLL_fprintf(CRTDLL_stderr,"\nrun-time error:\nError Code %d\n",err);
|
||
|
CRTDLL__exit(255);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* _assert (CRTDLL.041)
|
||
|
*
|
||
|
* Print an assertion message and call abort(). Really only present
|
||
|
* for win binaries. Winelib programs would typically use libc's
|
||
|
* version.
|
||
|
*/
|
||
|
VOID __cdecl CRTDLL__assert(LPVOID str, LPVOID file, UINT line)
|
||
|
{
|
||
|
CRTDLL_fprintf(CRTDLL_stderr,"Assertion failed: %s, file %s, line %d\n\n",
|
||
|
(char*)str,(char*)file, line);
|
||
|
CRTDLL_abort();
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* _c_exit (CRTDLL.047)
|
||
|
*/
|
||
|
VOID __cdecl CRTDLL__c_exit(VOID)
|
||
|
{
|
||
|
FIXME("not calling CRTDLL cleanup\n");
|
||
|
/* dont exit, return to caller */
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* _cexit (CRTDLL.049)
|
||
|
*/
|
||
|
VOID __cdecl CRTDLL__cexit(VOID)
|
||
|
{
|
||
|
FIXME("not calling CRTDLL cleanup\n");
|
||
|
/* dont exit, return to caller */
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* _exit (CRTDLL.087)
|
||
|
*/
|
||
|
VOID __cdecl CRTDLL__exit(LONG ret)
|
||
|
{
|
||
|
TRACE(":exit code %ld\n",ret);
|
||
|
CRTDLL__c_exit();
|
||
|
ExitProcess(ret);
|
||
|
}
|
||
|
|
||
|
/*********************************************************************
|
||
|
* _onexit (CRTDLL.236)
|
||
|
*
|
||
|
* Register a function to be called when the process terminates.
|
||
|
*/
|
||
|
atexit_function __cdecl CRTDLL__onexit( atexit_function func)
|
||
|
{
|
||
|
TRACE("registering function (%p)\n",func);
|
||
|
if (func && atexit_registered <= CRTDLL_ATEXIT_TABLE_SIZE - 1)
|
||
|
{
|
||
|
atexit_table[atexit_registered] = (atexit_function)func;
|
||
|
atexit_registered++;
|
||
|
return func; /* successful */
|
||
|
}
|
||
|
ERR(":Too many onexit() functions, or NULL function - not registered!\n");
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* exit (CRTDLL.359)
|
||
|
*/
|
||
|
void __cdecl CRTDLL_exit(DWORD ret)
|
||
|
{
|
||
|
TRACE(":exit code %ld\n",ret);
|
||
|
__CRTDLL__call_atexit();
|
||
|
CRTDLL__cexit();
|
||
|
ExitProcess(ret);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* abort (CRTDLL.335)
|
||
|
*
|
||
|
* Terminate the progam with an abnormal termination message. Returns
|
||
|
* 3 to the host OS.
|
||
|
*/
|
||
|
VOID __cdecl CRTDLL_abort()
|
||
|
{
|
||
|
CRTDLL_fprintf(CRTDLL_stderr,"\nabnormal program termination\n");
|
||
|
CRTDLL__exit(3);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* atexit (CRTDLL.345)
|
||
|
*
|
||
|
* Register a function to be called when the process terminates.
|
||
|
*/
|
||
|
INT __cdecl CRTDLL_atexit( atexit_function func)
|
||
|
{
|
||
|
return CRTDLL__onexit(func) == func ? 0 : -1;
|
||
|
}
|