Fixed some issues found by winapi_check.
[wine] / dlls / msvcrt / exit.c
1 /*
2  * msvcrt.dll exit functions
3  *
4  * Copyright 2000 Jon Griffiths
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include "msvcrt.h"
21
22 #include "msvcrt/conio.h"
23 #include "msvcrt/stdlib.h"
24 #include "mtdll.h"
25
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
29
30 /* MT */
31 #define LOCK_EXIT   _mlock(_EXIT_LOCK1)
32 #define UNLOCK_EXIT _munlock(_EXIT_LOCK1)
33
34 static _onexit_t *MSVCRT_atexit_table = NULL;
35 static int MSVCRT_atexit_table_size = 0;
36 static int MSVCRT_atexit_registered = 0; /* Points to free slot */
37
38 extern int MSVCRT_app_type;
39
40 /* INTERNAL: call atexit functions */
41 void __MSVCRT__call_atexit(void)
42 {
43   /* Note: should only be called with the exit lock held */
44   TRACE("%d atext functions to call\n", MSVCRT_atexit_registered);
45   /* Last registered gets executed first */
46   while (MSVCRT_atexit_registered > 0)
47   {
48     MSVCRT_atexit_registered--;
49     TRACE("next is %p\n",MSVCRT_atexit_table[MSVCRT_atexit_registered]);
50     if (MSVCRT_atexit_table[MSVCRT_atexit_registered])
51       (*MSVCRT_atexit_table[MSVCRT_atexit_registered])();
52     TRACE("returned\n");
53   }
54 }
55
56 /*********************************************************************
57  *              __dllonexit (MSVCRT.@)
58  */
59 _onexit_t __dllonexit(_onexit_t func, _onexit_t **start, _onexit_t **end)
60 {
61   _onexit_t *tmp;
62   int len;
63
64   TRACE("(%p,%p,%p)\n", func, start, end);
65
66   if (!start || !*start || !end || !*end)
67   {
68    FIXME("bad table\n");
69    return NULL;
70   }
71
72   len = (*end - *start);
73
74   TRACE("table start %p-%p, %d entries\n", *start, *end, len);
75
76   if (++len <= 0)
77     return NULL;
78
79   tmp = (_onexit_t *)MSVCRT_realloc(*start, len * sizeof(tmp));
80   if (!tmp)
81     return NULL;
82   *start = tmp;
83   *end = tmp + len;
84   tmp[len - 1] = func;
85   TRACE("new table start %p-%p, %d entries\n", *start, *end, len);
86   return func;
87 }
88
89 /*********************************************************************
90  *              _exit (MSVCRT.@)
91  */
92 void MSVCRT__exit(int exitcode)
93 {
94   TRACE("(%d)\n", exitcode);
95   ExitProcess(exitcode);
96 }
97
98 /*********************************************************************
99  *              _amsg_exit (MSVCRT.@)
100  */
101 void MSVCRT__amsg_exit(int errnum)
102 {
103   TRACE("(%d)\n", errnum);
104   /* FIXME: text for the error number. */
105   if (MSVCRT_app_type == 2)
106   {
107     /* FIXME: MsgBox */
108   }
109   _cprintf("\nruntime error R60%d\n",errnum);
110   MSVCRT__exit(255);
111 }
112
113 /*********************************************************************
114  *              abort (MSVCRT.@)
115  */
116 void MSVCRT_abort(void)
117 {
118   TRACE("(void)\n");
119   if (MSVCRT_app_type == 2)
120   {
121     /* FIXME: MsgBox */
122   }
123   _cputs("\nabnormal program termination\n");
124   MSVCRT__exit(3);
125 }
126
127 /*********************************************************************
128  *              _assert (MSVCRT.@)
129  */
130 void MSVCRT__assert(const char* str, const char* file, unsigned int line)
131 {
132   TRACE("(%s,%s,%d)\n",str,file,line);
133   if (MSVCRT_app_type == 2)
134   {
135     /* FIXME: MsgBox */
136   }
137   _cprintf("Assertion failed: %s, file %s, line %d\n\n",str,file, line);
138   MSVCRT_abort();
139 }
140
141 /*********************************************************************
142  *              _c_exit (MSVCRT.@)
143  */
144 void MSVCRT__c_exit(void)
145 {
146   TRACE("(void)\n");
147   /* All cleanup is done on DLL detach; Return to caller */
148 }
149
150 /*********************************************************************
151  *              _cexit (MSVCRT.@)
152  */
153 void MSVCRT__cexit(void)
154 {
155   TRACE("(void)\n");
156   /* All cleanup is done on DLL detach; Return to caller */
157 }
158
159 /*********************************************************************
160  *              _onexit (MSVCRT.@)
161  */
162 _onexit_t _onexit(_onexit_t func)
163 {
164   TRACE("(%p)\n",func);
165
166   if (!func)
167     return NULL;
168
169   LOCK_EXIT;
170   if (MSVCRT_atexit_registered > MSVCRT_atexit_table_size - 1)
171   {
172     _onexit_t *newtable;
173     TRACE("expanding table\n");
174     newtable = MSVCRT_calloc(sizeof(void *),MSVCRT_atexit_table_size + 32);
175     if (!newtable)
176     {
177       TRACE("failed!\n");
178       UNLOCK_EXIT;
179       return NULL;
180     }
181     memcpy (newtable, MSVCRT_atexit_table, MSVCRT_atexit_table_size);
182     MSVCRT_atexit_table_size += 32;
183     if (MSVCRT_atexit_table)
184       MSVCRT_free (MSVCRT_atexit_table);
185     MSVCRT_atexit_table = newtable;
186   }
187   MSVCRT_atexit_table[MSVCRT_atexit_registered] = func;
188   MSVCRT_atexit_registered++;
189   UNLOCK_EXIT;
190   return func;
191 }
192
193 /*********************************************************************
194  *              exit (MSVCRT.@)
195  */
196 void MSVCRT_exit(int exitcode)
197 {
198   TRACE("(%d)\n",exitcode);
199   LOCK_EXIT;
200   __MSVCRT__call_atexit();
201   UNLOCK_EXIT;
202   ExitProcess(exitcode);
203 }
204
205 /*********************************************************************
206  *              atexit (MSVCRT.@)
207  */
208 int MSVCRT_atexit(void (*func)(void))
209 {
210   TRACE("(%p)\n", func);
211   return _onexit((_onexit_t)func) == (_onexit_t)func ? 0 : -1;
212 }
213
214
215 /*********************************************************************
216  *              _purecall (MSVCRT.@)
217  */
218 void _purecall(void)
219 {
220   TRACE("(void)\n");
221   MSVCRT__amsg_exit( 25 );
222 }