mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 18:31:56 +00:00
[CRT]
- 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:
parent
482bde30b5
commit
92546d0ab1
7 changed files with 182 additions and 131 deletions
|
@ -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
|
||||
|
|
14
reactos/lib/sdk/crt/include/internal/misc.h
Normal file
14
reactos/lib/sdk/crt/include/internal/misc.h
Normal 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);
|
||||
|
47
reactos/lib/sdk/crt/misc/__crt_MessageBoxA.c
Normal file
47
reactos/lib/sdk/crt/misc/__crt_MessageBoxA.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
39
reactos/lib/sdk/crt/stdlib/_set_abort_behavior.c
Normal file
39
reactos/lib/sdk/crt/stdlib/_set_abort_behavior.c
Normal 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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue