- Use __debugbreak in _assert when user presses ignore in the message box
- Implement __crt_MessageBoxA and use it from _assert and abort
- Rewrite abort and _set_abort_behavior
- Add function headers and set BSD license for my code
- CORE-6594 #resolve

svn path=/trunk/; revision=58143
This commit is contained in:
Timo Kreuzer 2013-01-08 22:14:10 +00:00
parent 482bde30b5
commit 92546d0ab1
7 changed files with 182 additions and 131 deletions

View file

@ -120,6 +120,7 @@ list(APPEND CRT_SOURCE
mem/memcmp.c
mem/memccpy.c
mem/memicmp.c
misc/__crt_MessageBoxA.c
misc/amsg.c
misc/assert.c
misc/environ.c
@ -224,6 +225,7 @@ list(APPEND CRT_SOURCE
stdio/wstat.c
stdio/wstat64.c
stdlib/_exit.c
stdlib/_set_abort_behavior.c
stdlib/abort.c
stdlib/atexit.c
stdlib/ecvt.c

View file

@ -0,0 +1,14 @@
extern int msvcrt_error_mode;
extern int __app_type;
#define _UNKNOWN_APP 0
#define _CONSOLE_APP 1
#define _GUI_APP 2
int
__cdecl
__crt_MessageBoxA (
_In_opt_ const char *pszText,
_In_ unsigned int uType);

View file

@ -0,0 +1,47 @@
/*
* PROJECT: ReactOS C runtime library
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: lib/sdk/crt/__crt_MessageBoxA.c
* PURPOSE: __crt_MessageBoxA implementation
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
#include <precomp.h>
/*****************************************************************************
* \brief Displays a message box.
*
* \param pszText - The message to be displayed.
* \param uType - The contents and behavior of the message box.
* \return Identifies the button that was pressed by the user.
* \see MessageBox
*
*****************************************************************************/
int
__cdecl
__crt_MessageBoxA (
_In_opt_ const char *pszText,
_In_ unsigned int uType)
{
HMODULE hmodUser32;
int (WINAPI *pMessageBoxA)(HWND, LPCTSTR, LPCTSTR, UINT);
int iResult;
/* Get MessageBoxA function pointer */
hmodUser32 = LoadLibrary("user32.dll");
pMessageBoxA = (PVOID)GetProcAddress(hmodUser32, "MessageBoxA");
if (!pMessageBoxA)
{
abort();
}
/* Display a message box */
iResult = pMessageBoxA(NULL,
pszText,
"ReactOS C Runtime Library",
uType);
FreeLibrary(hmodUser32);
return iResult;
}

View file

@ -1,9 +1,12 @@
/* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
/*
* PROJECT: ReactOS C runtime library
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: lib/sdk/crt/assert.c
* PURPOSE: _assert implementation
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
#include <precomp.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
static const char formatstr[] =
"Assertion failed!\n\n"
@ -11,35 +14,33 @@ static const char formatstr[] =
"File: %s\n"
"Line: %ld\n\n"
"Expression: %s\n"
"Press Retry to debug the application\n";
"Press Retry to debug the application\n\0";
/*
* @implemented
*/
void _assert(const char *exp, const char *file, unsigned line)
void
_assert (
const char *exp,
const char *file,
unsigned line)
{
int (WINAPI *pMessageBoxA)(HWND, LPCTSTR, LPCTSTR, UINT);
HMODULE hmodUser32;
char achProgram[40];
char achProgram[MAX_PATH];
char *pszBuffer;
size_t len;
int iResult;
/* Assertion failed at foo.c line 45: x<y */
fprintf(stderr, "Assertion failed at %s line %d: %s\n", file, line, exp);
FIXME("Assertion failed at %s line %d: %s\n", file, line, exp);
/* First common debug message */
FIXME("Assertion failed: %s, file %s, line %d\n", exp, file, line);
/* Get MessageBoxA function pointer */
hmodUser32 = LoadLibrary("user32.dll");
pMessageBoxA = (PVOID)GetProcAddress(hmodUser32, "MessageBoxA");
if (!pMessageBoxA)
/* Check if output should go to stderr */
if (((msvcrt_error_mode == _OUT_TO_DEFAULT) && (__app_type == _CONSOLE_APP)) ||
(msvcrt_error_mode == _OUT_TO_STDERR))
{
/* Print 'Assertion failed: x<y, file foo.c, line 45' to stderr */
fprintf(stderr, "Assertion failed: %s, file %s, line %d\n", exp, file, line);
abort();
}
/* Get the file name of the module */
len = GetModuleFileNameA(NULL, achProgram, 40);
len = GetModuleFileNameA(NULL, achProgram, sizeof(achProgram));
/* Calculate full length of the message */
len += sizeof(formatstr) + len + strlen(exp) + strlen(file);
@ -51,22 +52,28 @@ void _assert(const char *exp, const char *file, unsigned line)
_snprintf(pszBuffer, len, formatstr, achProgram, file, line, exp);
/* Display a message box */
iResult = pMessageBoxA(NULL,
pszBuffer,
"ReactOS C Runtime Library",
MB_ABORTRETRYIGNORE | MB_ICONERROR);
iResult = __crt_MessageBoxA(pszBuffer, MB_ABORTRETRYIGNORE | MB_ICONERROR);
/* Free the buffer */
free(pszBuffer);
/* Does the user want to abort? */
if (iResult == IDABORT)
/* Does the user want to ignore? */
if (iResult == IDIGNORE)
{
abort();
/* Just return to the caller */
return;
}
/* Does the user want to debug? */
if (iResult == IDRETRY)
{
DbgRaiseAssertionFailure();
/* Break and return to the caller */
__debugbreak();
return;
}
/* Reset all abort flags (we don*t want another message box) and abort */
_set_abort_behavior(0, 0xffffffff);
abort();
}

View file

@ -60,6 +60,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
#include <internal/locale.h>
#include <internal/math.h>
#include <internal/mbstring.h>
#include <internal/misc.h>
#include <internal/mtdll.h>
#include <internal/rterror.h>
#include <internal/safecrt.h>

View file

@ -0,0 +1,39 @@
/*
* PROJECT: ReactOS C runtime library
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: lib/sdk/crt/_set_abort_behavior.c
* PURPOSE: _set_abort_behavior implementation
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
extern unsigned int __abort_behavior;
/*!
* \brief Specifies the behavior of the abort() function.
*
* \param flags - Value of the new flags.
* \param mask - Mask that specifies which flags to update.
* \return The old flags value.
*/
unsigned int
_cdecl
_set_abort_behavior(
unsigned int flags,
unsigned int mask)
{
unsigned int old_flags;
/* Save the old flags */
old_flags = __abort_behavior;
/* Reset all flags that are not in the mask */
flags &= mask;
/* Update the flags in the mask to the new flags value */
__abort_behavior &= ~mask;
__abort_behavior |= flags;
/* Return the old flags */
return old_flags;
}

View file

@ -1,114 +1,55 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/crt/stdlib/abort.c
* PURPOSE: Abnormal termination message
* PROGRAMER: Jon Griffiths
* Samuel Serapión
* PROJECT: ReactOS C runtime library
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: lib/sdk/crt/abort.c
* PURPOSE: abort implementation
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
/* based on wine exit.c */
#include <precomp.h>
#include "precomp.h"
#include <signal.h>
#include <internal/wine/msvcrt.h>
extern int msvcrt_error_mode;
extern int __app_type;
unsigned int msvcrt_abort_behavior = MSVCRT__WRITE_ABORT_MSG | MSVCRT__CALL_REPORTFAULT;
unsigned int __abort_behavior = _WRITE_ABORT_MSG | _CALL_REPORTFAULT;
/* avoid linking to user32 */
typedef HWND (WINAPI *GetActiveWindowPtr)(void);
static GetActiveWindowPtr pGetActiveWindow = NULL;
typedef int (WINAPI *MessageBoxIndirectWPtr)(const MSGBOXPARAMSW*);
static MessageBoxIndirectWPtr pMessageBoxIndirectW = NULL;
static const char abort_msg[] =
"This application has requested the Runtime to terminate in an unusual way.\n"
"Please contact the applications's support team for more information.\0";
static void DoMessageBoxW(const wchar_t *lead, const wchar_t *message)
{
const char szMsgBoxTitle[] = "ReactOS C++ Runtime Library";
const wchar_t message_format[] = {'%','s','\n','\n','P','r','o','g','r','a','m',':',' ','%','s','\n',
'%','s','\n','\n','P','r','e','s','s',' ','O','K',' ','t','o',' ','e','x','i','t',' ','t','h','e',' ',
'p','r','o','g','r','a','m',',',' ','o','r',' ','C','a','n','c','e','l',' ','t','o',' ','s','t','a','r','t',' ',
't','h','e',' ','d','e','b','b','u','g','e','r','.','\n',0};
MSGBOXPARAMSW msgbox;
wchar_t text[2048];
INT ret;
_snwprintf(text,sizeof(text),message_format, lead, _wpgmptr, message);
msgbox.cbSize = sizeof(msgbox);
msgbox.hwndOwner = pGetActiveWindow();
msgbox.hInstance = 0;
msgbox.lpszText = (LPCWSTR)text;
msgbox.lpszCaption = (LPCWSTR)szMsgBoxTitle;
msgbox.dwStyle = MB_OKCANCEL|MB_ICONERROR;
msgbox.lpszIcon = NULL;
msgbox.dwContextHelpId = 0;
msgbox.lpfnMsgBoxCallback = NULL;
msgbox.dwLanguageId = LANG_NEUTRAL;
ret = pMessageBoxIndirectW(&msgbox);
if (ret == IDCANCEL)
DebugBreak();
}
static void DoMessageBox(const char *lead, const char *message)
{
wchar_t leadW[1024], messageW[1024];
HMODULE huser32 = LoadLibrary("user32.dll");
if(huser32) {
pGetActiveWindow = (GetActiveWindowPtr)GetProcAddress(huser32, "GetActiveWindow");
pMessageBoxIndirectW = (MessageBoxIndirectWPtr)GetProcAddress(huser32, "MessageBoxIndirectW");
if(!pGetActiveWindow || !pMessageBoxIndirectW) {
FreeLibrary(huser32);
ERR("GetProcAddress failed!\n");
return;
}
}
else
{
ERR("Loading user32 failed!\n");
return;
}
mbstowcs(leadW, lead, 1024);
mbstowcs(messageW, message, 1024);
DoMessageBoxW(leadW, messageW);
FreeLibrary(huser32);
}
/*
* @implemented
/*!
* \brief Aborts the program.
*
* \note The function does not return.
*/
void abort()
void
__cdecl
abort (
void)
{
if (msvcrt_abort_behavior & MSVCRT__WRITE_ABORT_MSG)
{
if ((msvcrt_error_mode == MSVCRT__OUT_TO_MSGBOX) ||
((msvcrt_error_mode == MSVCRT__OUT_TO_DEFAULT) && (__app_type == 2)))
/* Check if a message should be output */
if (__abort_behavior & _WRITE_ABORT_MSG)
{
DoMessageBox("Runtime error!", "abnormal program termination");
/* Check if we should display a message box */
if (((msvcrt_error_mode == _OUT_TO_DEFAULT) && (__app_type == _GUI_APP)) ||
(msvcrt_error_mode == _OUT_TO_MSGBOX))
{
/* Output a message box */
__crt_MessageBoxA(abort_msg, MB_OK);
}
else
{
/* Print message to stderr */
fprintf(stderr, "%s\n", abort_msg);
}
}
else
_cputs("\nabnormal program termination\n");
}
raise(SIGABRT);
/* in case raise() returns */
_exit(3);
/* Check if faultrep handler should be called */
if (__abort_behavior & _CALL_REPORTFAULT)
{
/// \todo unimplemented
(void)0;
}
raise(SIGABRT);
_exit(3);
}
unsigned int CDECL _set_abort_behavior(unsigned int flags, unsigned int mask)
{
unsigned int old = msvcrt_abort_behavior;
TRACE("%x, %x\n", flags, mask);
if (mask & MSVCRT__CALL_REPORTFAULT)
FIXME("_WRITE_CALL_REPORTFAULT unhandled\n");
msvcrt_abort_behavior = (msvcrt_abort_behavior & ~mask) | (flags & mask);
return old;
}