xref: /reactos/sdk/lib/crt/startup/atonexit.c (revision 8a6d6530)
1c2c66affSColin Finck /**
2c2c66affSColin Finck  * This file has no copyright assigned and is placed in the Public Domain.
3c2c66affSColin Finck  * This file is part of the w64 mingw-runtime package.
4c2c66affSColin Finck  * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5c2c66affSColin Finck  */
6c2c66affSColin Finck 
7c2c66affSColin Finck #ifndef _DLL
8c2c66affSColin Finck #define _DLL
9c2c66affSColin Finck #endif
10c2c66affSColin Finck 
11c2c66affSColin Finck #include <oscalls.h>
12c2c66affSColin Finck #include <internal.h>
13c2c66affSColin Finck #include <stdlib.h>
14c2c66affSColin Finck #include <crtdefs.h>
15c2c66affSColin Finck #include <limits.h>
16c2c66affSColin Finck //#include <windows.h>
17c2c66affSColin Finck 
18c2c66affSColin Finck #define _EXIT_LOCK1 8
19c2c66affSColin Finck 
20c2c66affSColin Finck   void __cdecl _lock (int _File);
21c2c66affSColin Finck   void __cdecl _unlock (int _File);
22c2c66affSColin Finck 
23c2c66affSColin Finck _PVFV *__onexitbegin;
24c2c66affSColin Finck _PVFV *__onexitend;
25c2c66affSColin Finck 
262c791cddSTimo Kreuzer extern _onexit_t __cdecl __dllonexit (_onexit_t, _PVFV**, _PVFV**);
27c2c66affSColin Finck extern _onexit_t (__cdecl * __MINGW_IMP_SYMBOL(_onexit)) (_onexit_t func);
28c2c66affSColin Finck 
292c791cddSTimo Kreuzer /* INTERNAL: call atexit functions */
__call_atexit(void)302c791cddSTimo Kreuzer void __call_atexit(void)
312c791cddSTimo Kreuzer {
322c791cddSTimo Kreuzer     /* Note: should only be called with the exit lock held */
332c791cddSTimo Kreuzer     _PVFV *first, *last;
34c2c66affSColin Finck 
35*8a6d6530SJérôme Gardou     if (!__onexitbegin)
36*8a6d6530SJérôme Gardou         return;
372c791cddSTimo Kreuzer 
38*8a6d6530SJérôme Gardou     first =  (_PVFV *)_decode_pointer(__onexitbegin);
39*8a6d6530SJérôme Gardou     last = (_PVFV *)_decode_pointer(__onexitend);
402c791cddSTimo Kreuzer 
412c791cddSTimo Kreuzer     while (--last >= first)
422c791cddSTimo Kreuzer         if (*last)
432c791cddSTimo Kreuzer             (**last)();
442c791cddSTimo Kreuzer 
452c791cddSTimo Kreuzer     free(first);
46*8a6d6530SJérôme Gardou 
47*8a6d6530SJérôme Gardou     __onexitbegin = __onexitend = NULL;
482c791cddSTimo Kreuzer }
492c791cddSTimo Kreuzer 
502c791cddSTimo Kreuzer /* Choose a different name to prevent name conflicts. The CRT one works fine.  */
512c791cddSTimo Kreuzer _onexit_t __cdecl _onexit(_onexit_t func);
522c791cddSTimo Kreuzer 
_onexit(_onexit_t func)532c791cddSTimo Kreuzer _onexit_t __cdecl _onexit(_onexit_t func)
54c2c66affSColin Finck {
55c2c66affSColin Finck     _PVFV *onexitbegin;
56c2c66affSColin Finck     _PVFV *onexitend;
57c2c66affSColin Finck     _onexit_t retval;
58c2c66affSColin Finck 
59*8a6d6530SJérôme Gardou #ifndef CRTDLL
60*8a6d6530SJérôme Gardou     if (__onexitbegin == (_PVFV *) -1)
61c2c66affSColin Finck         return (* __MINGW_IMP_SYMBOL(_onexit)) (func);
622c791cddSTimo Kreuzer #endif
63*8a6d6530SJérôme Gardou 
64c2c66affSColin Finck     _lock (_EXIT_LOCK1);
65*8a6d6530SJérôme Gardou 
66*8a6d6530SJérôme Gardou     if (!__onexitbegin)
67*8a6d6530SJérôme Gardou     {
68*8a6d6530SJérôme Gardou         /* First time we are called. Initialize our array */
69*8a6d6530SJérôme Gardou         onexitbegin = calloc(1, sizeof(*onexitbegin));
70*8a6d6530SJérôme Gardou         if (!onexitbegin)
71*8a6d6530SJérôme Gardou         {
72*8a6d6530SJérôme Gardou             _unlock(_EXIT_LOCK1);
73*8a6d6530SJérôme Gardou             return NULL;
74*8a6d6530SJérôme Gardou         }
75*8a6d6530SJérôme Gardou         onexitend = onexitbegin;
76*8a6d6530SJérôme Gardou     }
77*8a6d6530SJérôme Gardou     else
78*8a6d6530SJérôme Gardou     {
79c2c66affSColin Finck         onexitbegin = (_PVFV *) _decode_pointer (__onexitbegin);
80c2c66affSColin Finck         onexitend = (_PVFV *) _decode_pointer (__onexitend);
81*8a6d6530SJérôme Gardou     }
82c2c66affSColin Finck 
83c2c66affSColin Finck     retval = __dllonexit (func, &onexitbegin, &onexitend);
84c2c66affSColin Finck 
85*8a6d6530SJérôme Gardou     if (retval != NULL)
86*8a6d6530SJérôme Gardou     {
87*8a6d6530SJérôme Gardou         /* Update our globals in case of success */
88c2c66affSColin Finck         __onexitbegin = (_PVFV *) _encode_pointer (onexitbegin);
89c2c66affSColin Finck         __onexitend = (_PVFV *) _encode_pointer (onexitend);
90*8a6d6530SJérôme Gardou     }
91*8a6d6530SJérôme Gardou 
92c2c66affSColin Finck     _unlock (_EXIT_LOCK1);
93c2c66affSColin Finck     return retval;
94c2c66affSColin Finck }
95c2c66affSColin Finck 
96c2c66affSColin Finck int __cdecl
atexit(_PVFV func)97c2c66affSColin Finck atexit (_PVFV func)
98c2c66affSColin Finck {
992c791cddSTimo Kreuzer   return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
100c2c66affSColin Finck }
101