ReactOS 0.4.16-dev-2102-g4cf8777
exit.c
Go to the documentation of this file.
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 <conio.h>
21#include <process.h>
22#include <signal.h>
23#include <stdio.h>
24#include "msvcrt.h"
25#include "mtdll.h"
26#include "winuser.h"
27#include "wine/debug.h"
28
30
31/* MT */
32#define LOCK_EXIT _lock(_EXIT_LOCK1)
33#define UNLOCK_EXIT _unlock(_EXIT_LOCK1)
34
36
38
39typedef void (__stdcall *_tls_callback_type)(void*,ULONG,void*);
41
44{
45 0, 0, &MSVCRT_onexit_cs,
47 0, 0, { (DWORD_PTR)(__FILE__ ": MSVCRT_onexit_cs") }
48};
49static CRITICAL_SECTION MSVCRT_onexit_cs = { &MSVCRT_onexit_cs_debug, -1, 0, 0, 0, 0 };
50
51extern int MSVCRT_app_type;
52extern wchar_t *MSVCRT__wpgmptr;
53
54#if _MSVCR_VER > 0 || defined(_DEBUG)
55static unsigned int MSVCRT_abort_behavior = _WRITE_ABORT_MSG | _CALL_REPORTFAULT;
56#endif
57
59
61
63{
64 if (!table)
65 return -1;
66
67 if (table->_first == table->_end)
68 table->_last = table->_end = table->_first = NULL;
69 return 0;
70}
71
73{
74 if (!table)
75 return -1;
76
78 if (!table->_first)
79 {
80 table->_first = calloc(32, sizeof(void *));
81 if (!table->_first)
82 {
83 WARN("failed to allocate initial table.\n");
85 return -1;
86 }
87 table->_last = table->_first;
88 table->_end = table->_first + 32;
89 }
90
91 /* grow if full */
92 if (table->_last == table->_end)
93 {
94 int len = table->_end - table->_first;
95 _PVFV *tmp = realloc(table->_first, 2 * len * sizeof(void *));
96 if (!tmp)
97 {
98 WARN("failed to grow table.\n");
100 return -1;
101 }
102 table->_first = tmp;
103 table->_end = table->_first + 2 * len;
104 table->_last = table->_first + len;
105 }
106
107 *table->_last = (_PVFV)func;
108 table->_last++;
110 return 0;
111}
112
114{
116 _PVFV *func;
117
118 if (!table)
119 return -1;
120
122 if (!table->_first || table->_first >= table->_last)
123 {
125 return 0;
126 }
127 copy._first = table->_first;
128 copy._last = table->_last;
129 copy._end = table->_end;
130 memset(table, 0, sizeof(*table));
133
134 for (func = copy._last - 1; func >= copy._first; func--)
135 {
136 if (*func)
137 (*func)();
138 }
139
140 free(copy._first);
141 return 0;
142}
143
144static void call_atexit(void)
145{
146 /* Note: should only be called with the exit lock held */
149}
150
151/*********************************************************************
152 * __dllonexit (MSVCRT.@)
153 */
155{
156 _onexit_t *tmp;
157 int len;
158
159 TRACE("(%p,%p,%p)\n", func, start, end);
160
161 if (!start || !*start || !end || !*end)
162 {
163 FIXME("bad table\n");
164 return NULL;
165 }
166
167 len = (*end - *start);
168
169 TRACE("table start %p-%p, %d entries\n", *start, *end, len);
170
171 if (++len <= 0)
172 return NULL;
173
174 tmp = realloc(*start, len * sizeof(*tmp));
175 if (!tmp)
176 return NULL;
177 *start = tmp;
178 *end = tmp + len;
179 tmp[len - 1] = func;
180 TRACE("new table start %p-%p, %d entries\n", *start, *end, len);
181 return func;
182}
183
184/*********************************************************************
185 * _exit (MSVCRT.@)
186 */
187void CDECL _exit(int exitcode)
188{
189 TRACE("(%d)\n", exitcode);
190 ExitProcess(exitcode);
191}
192
193/* Print out an error message with an option to debug */
194static void DoMessageBoxW(const wchar_t *lead, const wchar_t *message)
195{
196 MSGBOXPARAMSW msgbox;
197 wchar_t text[2048];
198 INT ret;
199
200 _snwprintf(text, ARRAY_SIZE(text), L"%ls\n\nProgram: %ls\n%ls\n\n"
201 L"Press OK to exit the program, or Cancel to start the Wine debugger.\n",
202 lead, MSVCRT__wpgmptr, message);
203
204 msgbox.cbSize = sizeof(msgbox);
205 msgbox.hwndOwner = GetActiveWindow();
206 msgbox.hInstance = 0;
207 msgbox.lpszText = text;
208 msgbox.lpszCaption = L"Wine C++ Runtime Library";
210 msgbox.lpszIcon = NULL;
211 msgbox.dwContextHelpId = 0;
212 msgbox.lpfnMsgBoxCallback = NULL;
213 msgbox.dwLanguageId = LANG_NEUTRAL;
214
215 ret = MessageBoxIndirectW(&msgbox);
216 if (ret == IDCANCEL)
217 DebugBreak();
218}
219
220static void DoMessageBox(const char *lead, const char *message)
221{
222 wchar_t leadW[1024], messageW[1024];
223
224 mbstowcs(leadW, lead, 1024);
225 mbstowcs(messageW, message, 1024);
226
227 DoMessageBoxW(leadW, messageW);
228}
229
230/*********************************************************************
231 * _amsg_exit (MSVCRT.@)
232 */
233void CDECL _amsg_exit(int errnum)
234{
235 TRACE("(%d)\n", errnum);
236
239 {
240 char text[32];
241 sprintf(text, "Error: R60%d",errnum);
242 DoMessageBox("Runtime error!", text);
243 }
244 else
245 _cprintf("\nruntime error R60%d\n",errnum);
246 _aexit_rtn(255);
247}
248
249/*********************************************************************
250 * abort (MSVCRT.@)
251 */
252void CDECL abort(void)
253{
254 TRACE("()\n");
255
256#if (_MSVCR_VER > 0 && _MSVCR_VER < 100) || _MSVCR_VER == 120 || defined(_DEBUG)
257 if (MSVCRT_abort_behavior & _WRITE_ABORT_MSG)
258 {
261 {
262 DoMessageBox("Runtime error!", "abnormal program termination");
263 }
264 else
265 _cputs("\nabnormal program termination\n");
266 }
267#endif
268 raise(SIGABRT);
269 /* in case raise() returns */
270 _exit(3);
271}
272
273#if _MSVCR_VER>=80
274/*********************************************************************
275 * _set_abort_behavior (MSVCR80.@)
276 */
277unsigned int CDECL _set_abort_behavior(unsigned int flags, unsigned int mask)
278{
279 unsigned int old = MSVCRT_abort_behavior;
280
281 TRACE("%x, %x\n", flags, mask);
283 FIXME("_WRITE_CALL_REPORTFAULT unhandled\n");
284
285 MSVCRT_abort_behavior = (MSVCRT_abort_behavior & ~mask) | (flags & mask);
286 return old;
287}
288#endif
289
290/*********************************************************************
291 * _wassert (MSVCRT.@)
292 */
293void DECLSPEC_NORETURN CDECL _wassert(const wchar_t* str, const wchar_t* file, unsigned int line)
294{
295 ERR("(%s,%s,%d)\n", debugstr_w(str), debugstr_w(file), line);
296
299 {
300 wchar_t text[2048];
301 _snwprintf(text, sizeof(text), L"File: %ls\nLine: %d\n\nExpression: \"%ls\"", file, line, str);
302 DoMessageBoxW(L"Assertion failed!", text);
303 }
304 else
305 fwprintf(stderr, L"Assertion failed: %ls, file %ls, line %d\n\n", str, file, line);
306
307 raise(SIGABRT);
308 _exit(3);
309}
310
311/*********************************************************************
312 * _assert (MSVCRT.@)
313 */
314void DECLSPEC_NORETURN CDECL _assert(const char* str, const char* file, unsigned int line)
315{
316 wchar_t strW[1024], fileW[1024];
317
318 mbstowcs(strW, str, 1024);
319 mbstowcs(fileW, file, 1024);
320
322}
323
324/*********************************************************************
325 * _c_exit (MSVCRT.@)
326 */
327void CDECL _c_exit(void)
328{
329 TRACE("(void)\n");
330 /* All cleanup is done on DLL detach; Return to caller */
331}
332
333/*********************************************************************
334 * _cexit (MSVCRT.@)
335 */
336void CDECL _cexit(void)
337{
338 TRACE("(void)\n");
339 LOCK_EXIT;
340 call_atexit();
342}
343
344/*********************************************************************
345 * _onexit (MSVCRT.@)
346 */
348{
349 TRACE("(%p)\n",func);
350
351 if (!func)
352 return NULL;
353
354 LOCK_EXIT;
357
358 return func;
359}
360
361/*********************************************************************
362 * exit (MSVCRT.@)
363 */
364void CDECL exit(int exitcode)
365{
367 void (WINAPI *pCorExitProcess)(int);
368
369 TRACE("(%d)\n",exitcode);
370 _cexit();
371
372 hmscoree = GetModuleHandleW(L"mscoree");
373
374 if (hmscoree)
375 {
376 pCorExitProcess = (void*)GetProcAddress(hmscoree, "CorExitProcess");
377
378 if (pCorExitProcess)
379 pCorExitProcess(exitcode);
380 }
381
382 ExitProcess(exitcode);
383}
384
385/*********************************************************************
386 * atexit (MSVCRT.@)
387 */
388int CDECL MSVCRT_atexit(void (__cdecl *func)(void))
389{
390 TRACE("(%p)\n", func);
391 return _onexit((_onexit_t)func) == (_onexit_t)func ? 0 : -1;
392}
393
394#if _MSVCR_VER >= 140
395static _onexit_table_t MSVCRT_quick_exit_table;
396
397/*********************************************************************
398 * _crt_at_quick_exit (UCRTBASE.@)
399 */
400int CDECL _crt_at_quick_exit(void (__cdecl *func)(void))
401{
402 TRACE("(%p)\n", func);
403 return register_onexit_function(&MSVCRT_quick_exit_table, (_onexit_t)func);
404}
405
406/*********************************************************************
407 * quick_exit (UCRTBASE.@)
408 */
409void CDECL quick_exit(int exitcode)
410{
411 TRACE("(%d)\n", exitcode);
412
413 execute_onexit_table(&MSVCRT_quick_exit_table);
414 _exit(exitcode);
415}
416
417/*********************************************************************
418 * _crt_atexit (UCRTBASE.@)
419 */
420int CDECL _crt_atexit(void (__cdecl *func)(void))
421{
422 TRACE("(%p)\n", func);
423 return _onexit((_onexit_t)func) == (_onexit_t)func ? 0 : -1;
424}
425
426/*********************************************************************
427 * _initialize_onexit_table (UCRTBASE.@)
428 */
430{
431 TRACE("(%p)\n", table);
432
434}
435
436/*********************************************************************
437 * _register_onexit_function (UCRTBASE.@)
438 */
440{
441 TRACE("(%p %p)\n", table, func);
442
444}
445
446/*********************************************************************
447 * _execute_onexit_table (UCRTBASE.@)
448 */
450{
451 TRACE("(%p)\n", table);
452
454}
455#endif
456
457/*********************************************************************
458 * _register_thread_local_exe_atexit_callback (UCRTBASE.@)
459 */
461{
462 TRACE("(%p)\n", callback);
464}
465
466#if _MSVCR_VER>=71
467/*********************************************************************
468 * _set_purecall_handler (MSVCR71.@)
469 */
471{
473
474 TRACE("(%p)\n", function);
475 purecall_handler = function;
476 return ret;
477}
478#endif
479
480#if _MSVCR_VER>=80
481/*********************************************************************
482 * _get_purecall_handler (MSVCR80.@)
483 */
485{
486 TRACE("\n");
487 return purecall_handler;
488}
489#endif
490
491/*********************************************************************
492 * _purecall (MSVCRT.@)
493 */
494void CDECL _purecall(void)
495{
496 TRACE("(void)\n");
497
500 _amsg_exit( 25 );
501}
502
503/******************************************************************************
504 * _set_error_mode (MSVCRT.@)
505 *
506 * Set the error mode, which describes where the C run-time writes error messages.
507 *
508 * PARAMS
509 * mode - the new error mode
510 *
511 * RETURNS
512 * The old error mode.
513 *
514 */
516{
517
518 const int old = MSVCRT_error_mode;
519 if ( _REPORT_ERRMODE != mode ) {
521 }
522 return old;
523}
aexit_t _aexit_rtn
Definition: amsg.c:39
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define NULL
Definition: types.h:112
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define GetProcAddress(x, y)
Definition: compat.h:753
static const WCHAR messageW[]
Definition: error.c:33
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1489
const WCHAR * text
Definition: package.c:1794
int CDECL _cputs(const char *str)
Definition: console.c:78
int WINAPIV _cprintf(const char *format,...)
Definition: console.c:563
int CDECL raise(int sig)
Definition: except.c:682
#define LOCK_EXIT
Definition: exit.c:32
wchar_t * MSVCRT__wpgmptr
Definition: data.c:61
static void DoMessageBox(const char *lead, const char *message)
Definition: exit.c:220
static int execute_onexit_table(_onexit_table_t *table)
Definition: exit.c:113
#define UNLOCK_EXIT
Definition: exit.c:33
static _onexit_table_t MSVCRT_atexit_table
Definition: exit.c:37
void DECLSPEC_NORETURN CDECL _wassert(const wchar_t *str, const wchar_t *file, unsigned int line)
Definition: exit.c:293
void(* CDECL)(int)
Definition: exit.c:60
static void DoMessageBoxW(const wchar_t *lead, const wchar_t *message)
Definition: exit.c:194
void CDECL _purecall(void)
Definition: exit.c:494
static _purecall_handler purecall_handler
Definition: exit.c:35
int CDECL _set_error_mode(int mode)
Definition: exit.c:515
void CDECL _amsg_exit(int errnum)
Definition: exit.c:233
void CDECL _register_thread_local_exe_atexit_callback(_tls_callback_type callback)
Definition: exit.c:460
static void call_atexit(void)
Definition: exit.c:144
void CDECL _c_exit(void)
Definition: exit.c:327
static CRITICAL_SECTION MSVCRT_onexit_cs
Definition: exit.c:42
static int register_onexit_function(_onexit_table_t *table, _onexit_t func)
Definition: exit.c:72
static _tls_callback_type tls_atexit_callback
Definition: exit.c:40
static CRITICAL_SECTION_DEBUG MSVCRT_onexit_cs_debug
Definition: exit.c:43
void DECLSPEC_NORETURN CDECL _assert(const char *str, const char *file, unsigned int line)
Definition: exit.c:314
void CDECL abort(void)
Definition: exit.c:252
void(__stdcall * _tls_callback_type)(void *, ULONG, void *)
Definition: exit.c:39
int MSVCRT_app_type
Definition: data.c:59
void CDECL _exit(int exitcode)
Definition: exit.c:187
_onexit_t CDECL _onexit(_onexit_t func)
Definition: exit.c:347
_onexit_t CDECL __dllonexit(_onexit_t func, _onexit_t **start, _onexit_t **end)
Definition: exit.c:154
static int initialize_onexit_table(_onexit_table_t *table)
Definition: exit.c:62
int CDECL MSVCRT_atexit(void(__cdecl *func)(void))
Definition: exit.c:388
void CDECL _cexit(void)
Definition: exit.c:336
static int MSVCRT_error_mode
Definition: exit.c:58
int WINAPIV fwprintf(FILE *file, const wchar_t *format,...)
Definition: file.c:5628
#define __cdecl
Definition: corecrt.h:121
#define __stdcall
Definition: corecrt.h:120
#define DECLSPEC_NORETURN
Definition: corecrt.h:131
_ACRTIMP int __cdecl _initialize_onexit_table(_onexit_table_t *)
Definition: onexit.c:34
int(__cdecl * _onexit_t)(void)
_ACRTIMP int __cdecl _crt_atexit(_PVFV)
Definition: onexit.cpp:41
_ACRTIMP int __cdecl _register_onexit_function(_onexit_table_t *, _onexit_t)
Definition: onexit.c:48
_ACRTIMP int __cdecl _crt_at_quick_exit(_PVFV)
Definition: onexit.cpp:46
void(__cdecl * _PVFV)(void)
_ACRTIMP int __cdecl _execute_onexit_table(_onexit_table_t *)
Definition: onexit.c:91
#define stderr
_ACRTIMP int __cdecl _snwprintf(wchar_t *, size_t, const wchar_t *,...)
Definition: wcs.c:1493
_ACRTIMP DECLSPEC_NORETURN void __cdecl quick_exit(int)
Definition: exit.cpp:304
#define SIGABRT
Definition: signal.h:31
#define _CALL_REPORTFAULT
Definition: stdlib.h:80
_ACRTIMP _purecall_handler __cdecl _get_purecall_handler(void)
#define _REPORT_ERRMODE
Definition: stdlib.h:76
_ACRTIMP _purecall_handler __cdecl _set_purecall_handler(_purecall_handler)
Definition: purecall.c:9
#define _OUT_TO_MSGBOX
Definition: stdlib.h:75
#define _OUT_TO_DEFAULT
Definition: stdlib.h:73
_ACRTIMP unsigned int __cdecl _set_abort_behavior(unsigned int flags, unsigned int mask)
Specifies the behavior of the abort() function.
void(__cdecl * _purecall_handler)(void)
Definition: stdlib.h:255
#define _WRITE_ABORT_MSG
Definition: stdlib.h:79
static const WCHAR fileW[]
Definition: url.c:111
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
GLuint start
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLenum func
Definition: glext.h:6028
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum mode
Definition: glext.h:6217
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
#define debugstr_w
Definition: kernel32.h:32
#define sprintf
Definition: sprintf.c:45
static IPrintDialogCallback callback
Definition: printdlg.c:326
static HMODULE hmscoree
Definition: fusion.c:24
WCHAR strW[12]
Definition: clipboard.c:2025
#define calloc
Definition: rosglue.h:14
const WCHAR * str
#define LANG_NEUTRAL
Definition: nls.h:22
mbstowcs
Definition: stdlib.h:925
#define exit(n)
Definition: config.h:202
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwLanguageId
Definition: winuser.h:3447
LPCWSTR lpszCaption
Definition: winuser.h:3442
DWORD_PTR dwContextHelpId
Definition: winuser.h:3445
HWND hwndOwner
Definition: winuser.h:3439
LPCWSTR lpszIcon
Definition: winuser.h:3444
MSGBOXCALLBACK lpfnMsgBoxCallback
Definition: winuser.h:3446
LPCWSTR lpszText
Definition: winuser.h:3441
HINSTANCE hInstance
Definition: winuser.h:3440
DWORD dwStyle
Definition: winuser.h:3443
Definition: fci.c:127
Definition: parser.c:49
Definition: tftpd.h:60
#define DWORD_PTR
Definition: treelist.c:76
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI DebugBreak(void)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define WINAPI
Definition: msvc.h:6
HWND WINAPI GetActiveWindow(void)
Definition: winpos.c:138
#define IDCANCEL
Definition: winuser.h:842
#define MB_ICONERROR
Definition: winuser.h:798
#define MB_OKCANCEL
Definition: winuser.h:815
int WINAPI MessageBoxIndirectW(_In_ CONST MSGBOXPARAMSW *lpmbp)