1 /* taken from wine exit.c */ 2 #include <precomp.h> 3 4 _onexit_t *atexit_table = NULL; 5 int atexit_table_size = 0; 6 int atexit_registered = 0; /* Points to free slot */ 7 8 /* INTERNAL: call atexit functions */ 9 void __call_atexit(void) 10 { 11 /* Note: should only be called with the exit lock held */ 12 TRACE("%d atext functions to call\n", atexit_registered); 13 /* Last registered gets executed first */ 14 while (atexit_registered > 0) 15 { 16 atexit_registered--; 17 TRACE("next is %p\n",atexit_table[atexit_registered]); 18 if (atexit_table[atexit_registered]) 19 (*atexit_table[atexit_registered])(); 20 TRACE("returned\n"); 21 } 22 } 23 24 /********************************************************************* 25 * __dllonexit (MSVCRT.@) 26 */ 27 _onexit_t CDECL __dllonexit(_onexit_t func, _onexit_t **start, _onexit_t **end) 28 { 29 _onexit_t *tmp; 30 size_t len; 31 32 TRACE("(%p,%p,%p)\n", func, start, end); 33 34 if (!start || !*start || !end || !*end) 35 { 36 FIXME("bad table\n"); 37 return NULL; 38 } 39 40 len = (*end - *start); 41 42 TRACE("table start %p-%p, %d entries\n", *start, *end, len); 43 44 if (++len <= 0) 45 return NULL; 46 47 tmp = realloc(*start, len * sizeof(_onexit_t)); 48 if (!tmp) 49 return NULL; 50 *start = tmp; 51 *end = tmp + len; 52 tmp[len - 1] = func; 53 TRACE("new table start %p-%p, %d entries\n", *start, *end, len); 54 return func; 55 } 56 57 /********************************************************************* 58 * _onexit (MSVCRT.@) 59 */ 60 _onexit_t CDECL _onexit(_onexit_t func) 61 { 62 TRACE("(%p)\n",func); 63 64 if (!func) 65 return NULL; 66 67 LOCK_EXIT; 68 if (atexit_registered > atexit_table_size - 1) 69 { 70 _onexit_t *newtable; 71 TRACE("expanding table\n"); 72 newtable = calloc(atexit_table_size + 32, sizeof(_onexit_t)); 73 if (!newtable) 74 { 75 TRACE("failed!\n"); 76 UNLOCK_EXIT; 77 return NULL; 78 } 79 memcpy (newtable, atexit_table, atexit_table_size*sizeof(_onexit_t)); 80 atexit_table_size += 32; 81 free (atexit_table); 82 atexit_table = newtable; 83 } 84 atexit_table[atexit_registered] = func; 85 atexit_registered++; 86 UNLOCK_EXIT; 87 return func; 88 } 89 90 /********************************************************************* 91 * atexit (MSVCRT.@) 92 */ 93 int CDECL atexit(void (*func)(void)) 94 { 95 TRACE("(%p)\n", func); 96 return _onexit((_onexit_t)func) == (_onexit_t)func ? 0 : -1; 97 } 98 99