ReactOS 0.4.16-dev-1109-gd06d9f3
report_runtime_error.cpp
Go to the documentation of this file.
1/***
2*report_runtime_error.cpp - startup error messages
3*
4* Copyright (c) Microsoft Corporation. All rights reserved.
5*
6*Purpose:
7* Prints out banner for runtime error messages.
8*
9*******************************************************************************/
10
11#include <corecrt_internal.h>
12#include <stdlib.h>
13
14
15
16// This is used during the expansion of the runtime error text.
17#define EOL L"\r\n"
18
19static bool __cdecl issue_debug_notification(wchar_t const* const message) throw()
20{
21 // This is referenced only in the Debug CRT build
23
24#ifdef _DEBUG
25 switch (_CrtDbgReportW(_CRT_ERROR, nullptr, 0, nullptr, L"%ls", message))
26 {
27 case 1:
29 return true;
30
31 case 0:
32 return true;
33 }
34#endif // _DEBUG
35
36 return false;
37}
38
39
40
41
42// Enclaves do not support error messages outside of OutputDebugString.
43#ifdef _UCRT_ENCLAVE_BUILD
44
45extern "C" void __cdecl __acrt_report_runtime_error(wchar_t const* const message)
46{
47 // Report the error using the debug
49}
50
51#else /* ^^^ _UCRT_ENCLAVE_BUILD ^^^ // vvv !_UCRT_ENCLAVE_BUILD vvv */
52
53/*
54 * __acrt_app_type, together with __error_mode, determine how error messages
55 * are written out.
56 */
58
59/***
60*void _set_app_type(int apptype) - interface to change __acrt_app_type
61*
62*Purpose:
63* Set, or change, the value of __acrt_app_type.
64*
65* Set the default debug lib report destination for console apps.
66*
67* This function is for INTERNAL USE ONLY.
68*
69*Entry:
70* int modeval = _crt_unknown_app, unknown
71* _crt_console_app, console, or command line, application
72* _crt_gui_app, GUI, or Windows, application
73*
74*Exit:
75*
76*Exceptions:
77*
78*******************************************************************************/
79
80extern "C" void __cdecl _set_app_type(_crt_app_type const new_app_type)
81{
82 __acrt_app_type = new_app_type;
83}
84
86{
87 return __acrt_app_type;
88}
89
90
91
93{
94 int const error_mode = _set_error_mode(_REPORT_ERRMODE);
95
96 if (error_mode == _OUT_TO_STDERR)
97 {
98 return true;
99 }
100
101 if (error_mode == _OUT_TO_DEFAULT && __acrt_app_type == _crt_console_app)
102 {
103 return true;
104 }
105
106 return false;
107}
108
109
110
111static void write_string_to_console(wchar_t const* const wide_string) throw()
112{
114 if (handle == nullptr || handle == INVALID_HANDLE_VALUE)
115 {
116 return;
117 }
118
119 // We convert the wide string to a narrow string by truncating each character.
120 // Currently, the text for each runtime error consists only of ASCII, so this
121 // is acceptable. If the error text is ever localized, this would need to
122 // change.
123 size_t const narrow_buffer_count = 500;
124 char narrow_buffer[narrow_buffer_count];
125
126 char* const narrow_first = narrow_buffer;
127 char* const narrow_last = narrow_first + narrow_buffer_count;
128
129 // Note that this loop copies the null terminator if the loop terminates
130 // befoe running out of buffer space:
131 char* narrow_it = narrow_first;
132 wchar_t const* wide_it = wide_string;
133 do
134 {
135 *narrow_it = static_cast<char>(*wide_it);
136 }
137 while (++narrow_it != narrow_last && *wide_it++ != '\0');
138
139 // If we did run out of buffer space, this will null-terminate the text that
140 // we were able to copy:
141 *(narrow_last - 1) = '\0';
142
143 DWORD const bytes_to_write = static_cast<DWORD>(narrow_it - narrow_first - 1); // Account for null terminator
144 DWORD bytes_written = 0;
145 WriteFile(handle, narrow_buffer, bytes_to_write, &bytes_written, nullptr);
146}
147
148
149
150extern "C" void __cdecl __acrt_report_runtime_error(wchar_t const* const message)
151{
152 // Before we report the error via the normal path, report the error using
153 // the debug
155 {
156 return;
157 }
158
160 {
162 }
163 else
164 {
165 #define MSGTEXTPREFIX L"Runtime Error!\n\nProgram: "
166 static wchar_t outmsg[sizeof(MSGTEXTPREFIX) / sizeof(wchar_t) + _MAX_PATH + 2 + 500];
167 // runtime error msg + progname + 2 newline + runtime error text.
168 wchar_t* progname = &outmsg[sizeof(MSGTEXTPREFIX) / sizeof(wchar_t) - 1];
169 size_t progname_size = _countof(outmsg) - (progname - outmsg);
170 wchar_t* pch = progname;
171
172 _ERRCHECK(wcscpy_s(outmsg, _countof(outmsg), MSGTEXTPREFIX));
173
174 progname[MAX_PATH] = L'\0';
175 if (!GetModuleFileNameW(nullptr, progname, MAX_PATH))
176 {
177 _ERRCHECK(wcscpy_s(progname, progname_size, L"<program name unknown>"));
178 }
179
180 #define MAXLINELEN 60
181 if (wcslen(pch) + 1 > MAXLINELEN)
182 {
183 pch += wcslen(progname) + 1 - MAXLINELEN;
184 _ERRCHECK(wcsncpy_s(pch, progname_size - (pch - progname), L"...", 3));
185 }
186
187 _ERRCHECK(wcscat_s(outmsg, _countof(outmsg), L"\n\n"));
188 _ERRCHECK(wcscat_s(outmsg, _countof(outmsg), message));
189
190 // Okay to ignore return value here, this is just to display the message box.
191 // Only caller is abort() (so we shouldn't/can't handle IDABORT), so the process
192 // will end shortly.
194 outmsg,
195 L"Microsoft Visual C++ Runtime Library",
197 }
198}
199
200#endif /* _UCRT_ENCLAVE_BUILD */
#define __cdecl
Definition: accygwin.h:79
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
static const char * progname
Definition: cjpeg.c:137
int __cdecl __acrt_show_wide_message_box(_In_opt_z_ wchar_t const *text, _In_opt_z_ wchar_t const *caption, _In_ unsigned type)
#define _ERRCHECK(e)
_crt_app_type
@ _crt_console_app
@ _crt_unknown_app
#define _CRT_ERROR
Definition: crtdbg.h:21
#define _CrtDbgBreak()
Definition: crtdbg.h:103
EXTERN_C int __cdecl _CrtDbgReportW(int reportType, const wchar_t *filename, int linenumber, const wchar_t *moduleName, const wchar_t *format,...)
Definition: dbgrpt.cpp:483
result_buffer_count char *const _In_ int const _In_ bool const _In_ unsigned const _In_ STRFLT const _In_ bool const _Inout_ __crt_cached_ptd_host &ptd throw()
Definition: cvt.cpp:119
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
unsigned long DWORD
Definition: ntddk_ex.h:95
#define _REPORT_ERRMODE
Definition: stdlib.h:113
#define _OUT_TO_DEFAULT
Definition: stdlib.h:110
_Check_return_opt_ _CRTIMP int __cdecl _set_error_mode(_In_ int _Mode)
#define _OUT_TO_STDERR
Definition: stdlib.h:111
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define pch(ap)
Definition: match.c:418
#define _MAX_PATH
Definition: utility.h:77
#define wcscpy_s(d, l, s)
Definition: utility.h:201
#define wcsncpy_s(d, l, s, n)
Definition: utility.h:202
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define L(x)
Definition: ntvdm.h:50
static bool __cdecl should_write_error_to_console()
#define MSGTEXTPREFIX
void __cdecl __acrt_report_runtime_error(wchar_t const *const message)
static _crt_app_type __acrt_app_type
_crt_app_type __cdecl _query_app_type()
static void write_string_to_console(wchar_t const *const wide_string)
#define MAXLINELEN
static bool __cdecl issue_debug_notification(wchar_t const *const message)
void __cdecl _set_app_type(_crt_app_type const new_app_type)
#define _countof(array)
Definition: sndvol32.h:70
Definition: tftpd.h:60
INT CDECL wcscat_s(wchar_t *dst, size_t elem, const wchar_t *src)
Definition: wcs.c:406
#define STD_ERROR_HANDLE
Definition: winbase.h:295
#define MB_SETFOREGROUND
Definition: winuser.h:825
#define MB_ICONHAND
Definition: winuser.h:799
#define MB_TASKMODAL
Definition: winuser.h:827
#define MB_OK
Definition: winuser.h:801