[CRT]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Tue, 8 Jan 2013 22:14:10 +0000 (22:14 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Tue, 8 Jan 2013 22:14:10 +0000 (22:14 +0000)
- 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

reactos/lib/sdk/crt/crt.cmake
reactos/lib/sdk/crt/include/internal/misc.h [new file with mode: 0644]
reactos/lib/sdk/crt/misc/__crt_MessageBoxA.c [new file with mode: 0644]
reactos/lib/sdk/crt/misc/assert.c
reactos/lib/sdk/crt/precomp.h
reactos/lib/sdk/crt/stdlib/_set_abort_behavior.c [new file with mode: 0644]
reactos/lib/sdk/crt/stdlib/abort.c

index 8433a70..90eac84 100644 (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
diff --git a/reactos/lib/sdk/crt/include/internal/misc.h b/reactos/lib/sdk/crt/include/internal/misc.h
new file mode 100644 (file)
index 0000000..ab552fb
--- /dev/null
@@ -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);
+
diff --git a/reactos/lib/sdk/crt/misc/__crt_MessageBoxA.c b/reactos/lib/sdk/crt/misc/__crt_MessageBoxA.c
new file mode 100644 (file)
index 0000000..734f177
--- /dev/null
@@ -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;
+}
+
index 4619a4f..f25a593 100644 (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();
 }
+
index 4d01c7c..ec7a252 100644 (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>
diff --git a/reactos/lib/sdk/crt/stdlib/_set_abort_behavior.c b/reactos/lib/sdk/crt/stdlib/_set_abort_behavior.c
new file mode 100644 (file)
index 0000000..8628509
--- /dev/null
@@ -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;
+}
+
index c85d869..3a3abb6 100644 (file)
 /*
- * 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;
-
-/* avoid linking to user32 */
-typedef HWND (WINAPI *GetActiveWindowPtr)(void);
-static GetActiveWindowPtr pGetActiveWindow = NULL;
-typedef int (WINAPI *MessageBoxIndirectWPtr)(const MSGBOXPARAMSW*);
-static MessageBoxIndirectWPtr pMessageBoxIndirectW = NULL;
-
-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);
+unsigned int __abort_behavior =  _WRITE_ABORT_MSG | _CALL_REPORTFAULT;
 
-  DoMessageBoxW(leadW, messageW);
-  FreeLibrary(huser32); 
-}
+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";
 
-/*
- * @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);
-}
 
-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");
+    /* Check if faultrep handler should be called */
+    if (__abort_behavior & _CALL_REPORTFAULT)
+    {
+        /// \todo unimplemented
+        (void)0;
+    }
 
-  msvcrt_abort_behavior = (msvcrt_abort_behavior & ~mask) | (flags & mask);
-  return old;
+    raise(SIGABRT);
+    _exit(3);
 }
+