Updated.
[wine] / dlls / msvcrt / exit.c
1 /*
2  * msvcrt.dll exit functions
3  *
4  * Copyright 2000 Jon Griffiths
5  */
6 #include "msvcrt.h"
7
8 DEFAULT_DEBUG_CHANNEL(msvcrt);
9
10 /* MT */
11 extern CRITICAL_SECTION MSVCRT_exit_cs;
12 #define LOCK_EXIT      EnterCriticalSection(&MSVCRT_exit_cs)
13 #define UNLOCK_EXIT    LeaveCriticalSection(&MSVCRT_exit_cs)
14
15 typedef void (__cdecl *MSVCRT_atexit_func)(void);
16
17 static MSVCRT_atexit_func *MSVCRT_atexit_table = NULL;
18 static int MSVCRT_atexit_table_size = 0;
19 static int MSVCRT_atexit_registered = 0; /* Points to free slot */
20
21 extern int MSVCRT_app_type;
22 void *__cdecl MSVCRT_realloc(void *ptr, unsigned int size);
23
24 /* INTERNAL: call atexit functions */
25 void __MSVCRT__call_atexit(void)
26 {
27   /* Note: should only be called with the exit lock held */
28   TRACE("%d atext functions to call\n", MSVCRT_atexit_registered);
29   /* Last registered gets executed first */
30   while (MSVCRT_atexit_registered > 0)
31   {
32     MSVCRT_atexit_registered--;
33     TRACE("next is %p\n",MSVCRT_atexit_table[MSVCRT_atexit_registered]);
34     if (MSVCRT_atexit_table[MSVCRT_atexit_registered])
35       (*MSVCRT_atexit_table[MSVCRT_atexit_registered])();
36     TRACE("returned\n");
37   }
38 }
39
40 /*********************************************************************
41  *              __dllonexit (MSVCRT.@)
42  */
43 MSVCRT_atexit_func __cdecl MSVCRT___dllonexit(MSVCRT_atexit_func func,
44                                               MSVCRT_atexit_func **start,
45                                               MSVCRT_atexit_func **end)
46 {
47   MSVCRT_atexit_func *tmp;
48   int len;
49
50   TRACE("(%p,%p,%p)\n", func, start, end);
51
52   if (!start || !*start || !end || !*end)
53   {
54    FIXME("bad table\n");
55    return NULL;
56   }
57
58   len = (*end - *start);
59
60   TRACE("table start %p-%p, %d entries\n", *start, *end, len);
61
62   if (++len <= 0)
63     return NULL;
64
65   tmp = (MSVCRT_atexit_func *)MSVCRT_realloc(*start, len * sizeof(tmp));
66   if (!tmp)
67     return NULL;
68   *start = tmp;
69   *end = tmp + len;
70   tmp[len - 1] = func;
71   TRACE("new table start %p-%p, %d entries\n", *start, *end, len);
72   return func;
73 }
74
75 /*********************************************************************
76  *              _exit (MSVCRT.@)
77  */
78 void __cdecl MSVCRT__exit(int exitcode)
79 {
80   TRACE("(%d)\n", exitcode);
81   ExitProcess(exitcode);
82 }
83
84 /*********************************************************************
85  *              _amsg_exit (MSVCRT.@)
86  */
87 void __cdecl MSVCRT__amsg_exit(int errnum)
88 {
89   TRACE("(%d)\n", errnum);
90   /* FIXME: text for the error number. */
91   if (MSVCRT_app_type == 2)
92   {
93     /* FIXME: MsgBox */
94   }
95   MSVCRT__cprintf("\nruntime error R60%d\n",errnum);
96   MSVCRT__exit(255);
97 }
98
99 /*********************************************************************
100  *              abort (MSVCRT.@)
101  */
102 void __cdecl MSVCRT_abort(void)
103 {
104   TRACE("(void)\n");
105   if (MSVCRT_app_type == 2)
106   {
107     /* FIXME: MsgBox */
108   }
109   MSVCRT__cputs("\nabnormal program termination\n");
110   MSVCRT__exit(3);
111 }
112
113 /*********************************************************************
114  *              _assert (MSVCRT.@)
115  */
116 void __cdecl MSVCRT__assert(const char* str, const char* file, unsigned int line)
117 {
118   TRACE("(%s,%s,%d)\n",str,file,line);
119   if (MSVCRT_app_type == 2)
120   {
121     /* FIXME: MsgBox */
122   }
123   MSVCRT__cprintf("Assertion failed: %s, file %s, line %d\n\n",str,file, line);
124   MSVCRT_abort();
125 }
126
127 /*********************************************************************
128  *              _c_exit (MSVCRT.@)
129  */
130 void __cdecl MSVCRT__c_exit(void)
131 {
132   TRACE("(void)\n");
133   /* All cleanup is done on DLL detach; Return to caller */
134 }
135
136 /*********************************************************************
137  *              _cexit (MSVCRT.@)
138  */
139 void __cdecl MSVCRT__cexit(void)
140 {
141   TRACE("(void)\n");
142   /* All cleanup is done on DLL detach; Return to caller */
143 }
144
145 /*********************************************************************
146  *              _onexit (MSVCRT.@)
147  */
148  MSVCRT_atexit_func __cdecl MSVCRT__onexit(MSVCRT_atexit_func func)
149 {
150   TRACE("(%p)\n",func);
151
152   if (!func)
153     return NULL;
154
155   LOCK_EXIT;
156   if (MSVCRT_atexit_registered > MSVCRT_atexit_table_size - 1)
157   {
158     MSVCRT_atexit_func *newtable;
159     TRACE("expanding table\n");
160     newtable = MSVCRT_calloc(sizeof(void *),MSVCRT_atexit_table_size + 32);
161     if (!newtable)
162     {
163       TRACE("failed!\n");
164       UNLOCK_EXIT;
165       return NULL;
166     }
167     memcpy (newtable, MSVCRT_atexit_table, MSVCRT_atexit_table_size);
168     MSVCRT_atexit_table_size += 32;
169     if (MSVCRT_atexit_table)
170       MSVCRT_free (MSVCRT_atexit_table);
171     MSVCRT_atexit_table = newtable;
172   }
173   MSVCRT_atexit_table[MSVCRT_atexit_registered] = func;
174   MSVCRT_atexit_registered++;
175   UNLOCK_EXIT;
176   return func;
177 }
178
179 /*********************************************************************
180  *              exit (MSVCRT.@)
181  */
182 void __cdecl MSVCRT_exit(int exitcode)
183 {
184   TRACE("(%d)\n",exitcode);
185   LOCK_EXIT;
186   __MSVCRT__call_atexit();
187   UNLOCK_EXIT;
188   ExitProcess(exitcode);
189 }
190
191 /*********************************************************************
192  *              atexit (MSVCRT.@)
193  */
194 int __cdecl MSVCRT_atexit(MSVCRT_atexit_func func)
195 {
196   TRACE("(%p)\n", func);
197   return MSVCRT__onexit(func) == func ? 0 : -1;
198 }
199
200 /*********************************************************************
201  *              _purecall (MSVCRT.@)
202  */
203 void __cdecl MSVCRT__purecall(void)
204 {
205   TRACE("(void)\n");
206   MSVCRT__amsg_exit( 25 );
207 }