Release 1.3.7.
[wine/gsoc-2012-control.git] / dlls / msvcrt / exit.c
blob80749fc86f28f82789df3839bfa787f93c3b40d1
1 /*
2 * msvcrt.dll exit functions
4 * Copyright 2000 Jon Griffiths
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.
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.
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
20 #include <stdio.h>
21 #include "msvcrt.h"
22 #include "mtdll.h"
23 #include "winuser.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
28 /* MT */
29 #define LOCK_EXIT _mlock(_EXIT_LOCK1)
30 #define UNLOCK_EXIT _munlock(_EXIT_LOCK1)
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 static MSVCRT_purecall_handler purecall_handler = NULL;
37 static const char szMsgBoxTitle[] = "Wine C++ Runtime Library";
39 extern int MSVCRT_app_type;
40 extern char *MSVCRT__pgmptr;
42 void (*CDECL _aexit_rtn)(int) = MSVCRT__exit;
44 /* INTERNAL: call atexit functions */
45 static void __MSVCRT__call_atexit(void)
47 /* Note: should only be called with the exit lock held */
48 TRACE("%d atext functions to call\n", MSVCRT_atexit_registered);
49 /* Last registered gets executed first */
50 while (MSVCRT_atexit_registered > 0)
52 MSVCRT_atexit_registered--;
53 TRACE("next is %p\n",MSVCRT_atexit_table[MSVCRT_atexit_registered]);
54 if (MSVCRT_atexit_table[MSVCRT_atexit_registered])
55 (*MSVCRT_atexit_table[MSVCRT_atexit_registered])();
56 TRACE("returned\n");
60 /*********************************************************************
61 * __dllonexit (MSVCRT.@)
63 MSVCRT__onexit_t CDECL __dllonexit(MSVCRT__onexit_t func, MSVCRT__onexit_t **start, MSVCRT__onexit_t **end)
65 MSVCRT__onexit_t *tmp;
66 int len;
68 TRACE("(%p,%p,%p)\n", func, start, end);
70 if (!start || !*start || !end || !*end)
72 FIXME("bad table\n");
73 return NULL;
76 len = (*end - *start);
78 TRACE("table start %p-%p, %d entries\n", *start, *end, len);
80 if (++len <= 0)
81 return NULL;
83 tmp = MSVCRT_realloc(*start, len * sizeof(tmp));
84 if (!tmp)
85 return NULL;
86 *start = tmp;
87 *end = tmp + len;
88 tmp[len - 1] = func;
89 TRACE("new table start %p-%p, %d entries\n", *start, *end, len);
90 return func;
93 /*********************************************************************
94 * _exit (MSVCRT.@)
96 void CDECL MSVCRT__exit(int exitcode)
98 TRACE("(%d)\n", exitcode);
99 ExitProcess(exitcode);
102 /* Print out an error message with an option to debug */
103 static void DoMessageBox(LPCSTR lead, LPCSTR message)
105 MSGBOXPARAMSA msgbox;
106 char text[2048];
107 INT ret;
109 snprintf(text,sizeof(text),"%s\n\nProgram: %s\n%s\n\n"
110 "Press OK to exit the program, or Cancel to start the Wine debugger.\n ",
111 lead, MSVCRT__pgmptr, message);
113 msgbox.cbSize = sizeof(msgbox);
114 msgbox.hwndOwner = GetActiveWindow();
115 msgbox.hInstance = 0;
116 msgbox.lpszText = text;
117 msgbox.lpszCaption = szMsgBoxTitle;
118 msgbox.dwStyle = MB_OKCANCEL|MB_ICONERROR;
119 msgbox.lpszIcon = NULL;
120 msgbox.dwContextHelpId = 0;
121 msgbox.lpfnMsgBoxCallback = NULL;
122 msgbox.dwLanguageId = LANG_NEUTRAL;
124 ret = MessageBoxIndirectA(&msgbox);
125 if (ret == IDCANCEL)
126 DebugBreak();
129 /*********************************************************************
130 * _amsg_exit (MSVCRT.@)
132 void CDECL _amsg_exit(int errnum)
134 TRACE("(%d)\n", errnum);
135 /* FIXME: text for the error number. */
136 if (MSVCRT_app_type == 2)
138 char text[32];
139 sprintf(text, "Error: R60%d",errnum);
140 DoMessageBox("Runtime error!", text);
142 else
143 _cprintf("\nruntime error R60%d\n",errnum);
144 _aexit_rtn(255);
147 /*********************************************************************
148 * abort (MSVCRT.@)
150 void CDECL MSVCRT_abort(void)
152 TRACE("()\n");
153 if (MSVCRT_app_type == 2)
155 DoMessageBox("Runtime error!", "abnormal program termination");
157 else
158 _cputs("\nabnormal program termination\n");
159 MSVCRT_raise(MSVCRT_SIGABRT);
160 /* in case raise() returns */
161 MSVCRT__exit(3);
164 /*********************************************************************
165 * _assert (MSVCRT.@)
167 void CDECL MSVCRT__assert(const char* str, const char* file, unsigned int line)
169 TRACE("(%s,%s,%d)\n",str,file,line);
170 if (MSVCRT_app_type == 2)
172 char text[2048];
173 snprintf(text, sizeof(text), "File: %s\nLine: %d\n\nExpression: \"%s\"", file, line, str);
174 DoMessageBox("Assertion failed!", text);
176 else
177 _cprintf("Assertion failed: %s, file %s, line %d\n\n",str, file, line);
178 MSVCRT_raise(MSVCRT_SIGABRT);
179 /* in case raise() returns */
180 MSVCRT__exit(3);
183 /*********************************************************************
184 * _c_exit (MSVCRT.@)
186 void CDECL MSVCRT__c_exit(void)
188 TRACE("(void)\n");
189 /* All cleanup is done on DLL detach; Return to caller */
192 /*********************************************************************
193 * _cexit (MSVCRT.@)
195 void CDECL MSVCRT__cexit(void)
197 TRACE("(void)\n");
198 LOCK_EXIT;
199 __MSVCRT__call_atexit();
200 UNLOCK_EXIT;
203 /*********************************************************************
204 * _onexit (MSVCRT.@)
206 MSVCRT__onexit_t CDECL MSVCRT__onexit(MSVCRT__onexit_t func)
208 TRACE("(%p)\n",func);
210 if (!func)
211 return NULL;
213 LOCK_EXIT;
214 if (MSVCRT_atexit_registered > MSVCRT_atexit_table_size - 1)
216 MSVCRT__onexit_t *newtable;
217 TRACE("expanding table\n");
218 newtable = MSVCRT_calloc(sizeof(void *),MSVCRT_atexit_table_size + 32);
219 if (!newtable)
221 TRACE("failed!\n");
222 UNLOCK_EXIT;
223 return NULL;
225 memcpy (newtable, MSVCRT_atexit_table, MSVCRT_atexit_table_size);
226 MSVCRT_atexit_table_size += 32;
227 MSVCRT_free (MSVCRT_atexit_table);
228 MSVCRT_atexit_table = newtable;
230 MSVCRT_atexit_table[MSVCRT_atexit_registered] = func;
231 MSVCRT_atexit_registered++;
232 UNLOCK_EXIT;
233 return func;
236 /*********************************************************************
237 * exit (MSVCRT.@)
239 void CDECL MSVCRT_exit(int exitcode)
241 TRACE("(%d)\n",exitcode);
242 MSVCRT__cexit();
243 ExitProcess(exitcode);
246 /*********************************************************************
247 * atexit (MSVCRT.@)
249 int CDECL MSVCRT_atexit(void (*func)(void))
251 TRACE("(%p)\n", func);
252 return MSVCRT__onexit((MSVCRT__onexit_t)func) == (MSVCRT__onexit_t)func ? 0 : -1;
255 /* _set_purecall_handler - not exported in native msvcrt */
256 MSVCRT_purecall_handler CDECL _set_purecall_handler(MSVCRT_purecall_handler function)
258 MSVCRT_purecall_handler ret = purecall_handler;
260 TRACE("(%p)\n", function);
261 purecall_handler = function;
262 return ret;
265 /*********************************************************************
266 * _purecall (MSVCRT.@)
268 void CDECL _purecall(void)
270 TRACE("(void)\n");
272 if(purecall_handler)
273 purecall_handler();
274 _amsg_exit( 25 );