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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20 #include <stdio.h>
21 #include "msvcrt.h"
22 #include "mtdll.h"
23 #include "winuser.h"
24 #include "wine/debug.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
27
28 /* MT */
29 #define LOCK_EXIT _mlock(_EXIT_LOCK1)
30 #define UNLOCK_EXIT _munlock(_EXIT_LOCK1)
31
32 static MSVCRT__onexit_t *MSVCRT_atexit_table = NULL;
33 static int MSVCRT_atexit_table_size = 0;
34 static int MSVCRT_atexit_registered = 0; /* Points to free slot */
35
36 static const char szMsgBoxTitle[] = "Wine C++ Runtime Library";
37
38 extern int MSVCRT_app_type;
39 extern char *MSVCRT__pgmptr;
40
41 void (*CDECL _aexit_rtn)(int) = MSVCRT__exit;
42
43 /* INTERNAL: call atexit functions */
44 static void __MSVCRT__call_atexit(void)
45 {
46 /* Note: should only be called with the exit lock held */
47 TRACE("%d atext functions to call\n", MSVCRT_atexit_registered);
48 /* Last registered gets executed first */
49 while (MSVCRT_atexit_registered > 0)
50 {
51 MSVCRT_atexit_registered--;
52 TRACE("next is %p\n",MSVCRT_atexit_table[MSVCRT_atexit_registered]);
53 if (MSVCRT_atexit_table[MSVCRT_atexit_registered])
54 (*MSVCRT_atexit_table[MSVCRT_atexit_registered])();
55 TRACE("returned\n");
56 }
57 }
58
59 /*********************************************************************
60 * __dllonexit (MSVCRT.@)
61 */
62 MSVCRT__onexit_t CDECL __dllonexit(MSVCRT__onexit_t func, MSVCRT__onexit_t **start, MSVCRT__onexit_t **end)
63 {
64 MSVCRT__onexit_t *tmp;
65 int len;
66
67 TRACE("(%p,%p,%p)\n", func, start, end);
68
69 if (!start || !*start || !end || !*end)
70 {
71 FIXME("bad table\n");
72 return NULL;
73 }
74
75 len = (*end - *start);
76
77 TRACE("table start %p-%p, %d entries\n", *start, *end, len);
78
79 if (++len <= 0)
80 return NULL;
81
82 tmp = MSVCRT_realloc(*start, len * sizeof(tmp));
83 if (!tmp)
84 return NULL;
85 *start = tmp;
86 *end = tmp + len;
87 tmp[len - 1] = func;
88 TRACE("new table start %p-%p, %d entries\n", *start, *end, len);
89 return func;
90 }
91
92 /*********************************************************************
93 * _exit (MSVCRT.@)
94 */
95 void CDECL MSVCRT__exit(int exitcode)
96 {
97 TRACE("(%d)\n", exitcode);
98 ExitProcess(exitcode);
99 }
100
101 /* Print out an error message with an option to debug */
102 static void DoMessageBox(LPCSTR lead, LPCSTR message)
103 {
104 MSGBOXPARAMSA msgbox;
105 char text[2048];
106 INT ret;
107
108 snprintf(text,sizeof(text),"%s\n\nProgram: %s\n%s\n\n"
109 "Press OK to exit the program, or Cancel to start the Wine debugger.\n ",
110 lead, MSVCRT__pgmptr, message);
111
112 msgbox.cbSize = sizeof(msgbox);
113 msgbox.hwndOwner = GetActiveWindow();
114 msgbox.hInstance = 0;
115 msgbox.lpszText = text;
116 msgbox.lpszCaption = szMsgBoxTitle;
117 msgbox.dwStyle = MB_OKCANCEL|MB_ICONERROR;
118 msgbox.lpszIcon = NULL;
119 msgbox.dwContextHelpId = 0;
120 msgbox.lpfnMsgBoxCallback = NULL;
121 msgbox.dwLanguageId = LANG_NEUTRAL;
122
123 ret = MessageBoxIndirectA(&msgbox);
124 if (ret == IDCANCEL)
125 DebugBreak();
126 }
127
128 /*********************************************************************
129 * _amsg_exit (MSVCRT.@)
130 */
131 void CDECL _amsg_exit(int errnum)
132 {
133 TRACE("(%d)\n", errnum);
134 /* FIXME: text for the error number. */
135 if (MSVCRT_app_type == 2)
136 {
137 char text[32];
138 sprintf(text, "Error: R60%d",errnum);
139 DoMessageBox("Runtime error!", text);
140 }
141 else
142 _cprintf("\nruntime error R60%d\n",errnum);
143 _aexit_rtn(255);
144 }
145
146 /*********************************************************************
147 * abort (MSVCRT.@)
148 */
149 void CDECL MSVCRT_abort(void)
150 {
151 TRACE("()\n");
152 if (MSVCRT_app_type == 2)
153 {
154 DoMessageBox("Runtime error!", "abnormal program termination");
155 }
156 else
157 _cputs("\nabnormal program termination\n");
158 MSVCRT_raise(MSVCRT_SIGABRT);
159 /* in case raise() returns */
160 MSVCRT__exit(3);
161 }
162
163 /*********************************************************************
164 * _assert (MSVCRT.@)
165 */
166 void CDECL MSVCRT__assert(const char* str, const char* file, unsigned int line)
167 {
168 TRACE("(%s,%s,%d)\n",str,file,line);
169 if (MSVCRT_app_type == 2)
170 {
171 char text[2048];
172 snprintf(text, sizeof(text), "File: %s\nLine: %d\n\nExpression: \"%s\"", file, line, str);
173 DoMessageBox("Assertion failed!", text);
174 }
175 else
176 _cprintf("Assertion failed: %s, file %s, line %d\n\n",str, file, line);
177 MSVCRT_raise(MSVCRT_SIGABRT);
178 /* in case raise() returns */
179 MSVCRT__exit(3);
180 }
181
182 /*********************************************************************
183 * _c_exit (MSVCRT.@)
184 */
185 void CDECL MSVCRT__c_exit(void)
186 {
187 TRACE("(void)\n");
188 /* All cleanup is done on DLL detach; Return to caller */
189 }
190
191 /*********************************************************************
192 * _cexit (MSVCRT.@)
193 */
194 void CDECL MSVCRT__cexit(void)
195 {
196 TRACE("(void)\n");
197 LOCK_EXIT;
198 __MSVCRT__call_atexit();
199 UNLOCK_EXIT;
200 }
201
202 /*********************************************************************
203 * _onexit (MSVCRT.@)
204 */
205 MSVCRT__onexit_t CDECL MSVCRT__onexit(MSVCRT__onexit_t func)
206 {
207 TRACE("(%p)\n",func);
208
209 if (!func)
210 return NULL;
211
212 LOCK_EXIT;
213 if (MSVCRT_atexit_registered > MSVCRT_atexit_table_size - 1)
214 {
215 MSVCRT__onexit_t *newtable;
216 TRACE("expanding table\n");
217 newtable = MSVCRT_calloc(sizeof(void *),MSVCRT_atexit_table_size + 32);
218 if (!newtable)
219 {
220 TRACE("failed!\n");
221 UNLOCK_EXIT;
222 return NULL;
223 }
224 memcpy (newtable, MSVCRT_atexit_table, MSVCRT_atexit_table_size);
225 MSVCRT_atexit_table_size += 32;
226 MSVCRT_free (MSVCRT_atexit_table);
227 MSVCRT_atexit_table = newtable;
228 }
229 MSVCRT_atexit_table[MSVCRT_atexit_registered] = func;
230 MSVCRT_atexit_registered++;
231 UNLOCK_EXIT;
232 return func;
233 }
234
235 /*********************************************************************
236 * exit (MSVCRT.@)
237 */
238 void CDECL MSVCRT_exit(int exitcode)
239 {
240 TRACE("(%d)\n",exitcode);
241 MSVCRT__cexit();
242 ExitProcess(exitcode);
243 }
244
245 /*********************************************************************
246 * atexit (MSVCRT.@)
247 */
248 int CDECL MSVCRT_atexit(void (*func)(void))
249 {
250 TRACE("(%p)\n", func);
251 return MSVCRT__onexit((MSVCRT__onexit_t)func) == (MSVCRT__onexit_t)func ? 0 : -1;
252 }
253
254
255 /*********************************************************************
256 * _purecall (MSVCRT.@)
257 */
258 void CDECL _purecall(void)
259 {
260 TRACE("(void)\n");
261 _amsg_exit( 25 );
262 }
263
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.