xref: /reactos/sdk/lib/ucrt/misc/crtmbox.cpp (revision 04e0dc4a)
1 /***
2 *crtmbox.c - CRT MessageBoxA wrapper.
3 *
4 *       Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 *       Wrap MessageBoxA.
8 *
9 *******************************************************************************/
10 
11 #include <corecrt_internal.h>
12 #include <corecrt_internal_traits.h>
13 
14 
15 
16 namespace
17 {
18     template <typename Character>
19     struct message_box_arguments
20     {
21         Character const* _caption;
22         Character const* _text;
23         unsigned int     _type;
24         int              _result;
25     };
26 }
27 
28 template <typename Character>
common_show_message_box(Character const * const text,Character const * const caption,unsigned const type)29 static int __cdecl common_show_message_box(
30     Character const* const text,
31     Character const* const caption,
32     unsigned         const type
33     ) throw()
34 {
35     using traits = __crt_char_traits<Character>;
36 
37     bool const debugger_attached = IsDebuggerPresent();
38     if (debugger_attached)
39     {
40         // Output the message to the attached debugger.  This is useful when
41         // remotely debugging.
42         if (text)
43         {
44             traits::output_debug_string(text);
45         }
46 
47         // We do not want to display a message box if a debugger
48         // is already attached, unless it's a desktop app.
49         // Instead, let the caller know that we want to
50         // directly break into the debugger:
51         bool const is_desktop_app = __acrt_get_windowing_model_policy() == windowing_model_policy_hwnd;
52         if (!is_desktop_app)
53         {
54             return IDRETRY; // Retry = Break into the debugger
55         }
56     }
57 
58     bool const show_ui = __acrt_get_developer_information_policy() == developer_information_policy_ui;
59     if (!show_ui || !__acrt_can_show_message_box())
60     {
61         // If we can't get the message box pointers (perhaps because running on CoreSys),
62         // just abort, unless a debugger is attached--then break into the debugger instead.
63         // The message string was already output to the debugger above.
64         return debugger_attached ? IDRETRY : IDABORT;
65     }
66 
67     // If the current process isn't attached to a visible window station (e.g.
68     // a non-interactive service), then we need to set the MB_SERVICE_NOTIFICATION
69     // flag, otherwise the message box will be invisible, stalling the program.
70     if (!__acrt_is_interactive())
71     {
72         return traits::message_box(nullptr, text, caption, type | MB_SERVICE_NOTIFICATION);
73     }
74 
75     return traits::message_box(__acrt_get_parent_window(), text, caption, type);
76 }
77 
__acrt_show_narrow_message_box(char const * const text,char const * const caption,unsigned const type)78 extern "C" int __cdecl __acrt_show_narrow_message_box(
79     char const* const text,
80     char const* const caption,
81     unsigned    const type
82     )
83 {
84     return common_show_message_box(text, caption, type);
85 }
86 
__acrt_show_wide_message_box(wchar_t const * const text,wchar_t const * const caption,unsigned const type)87 extern "C" int __cdecl __acrt_show_wide_message_box(
88     wchar_t const* const text,
89     wchar_t const* const caption,
90     unsigned       const type
91     )
92 {
93     return common_show_message_box(text, caption, type);
94 }
95