[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / utilcode / utilmessagebox.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //*****************************************************************************
5 // UtilMessageBox.cpp
6 //
7
8 //
9 // This module contains the message box utility code for the CLR. It is used
10 // by code in the CLR itself as well as other tools that build in the CLR tree.
11 // For message boxes inside the ExecutionEngine, EEMessageBox must be used
12 // instead of the these APIs.
13 //
14 //*****************************************************************************
15 #include "stdafx.h"                     // Standard header.
16 #include <utilcode.h>                   // Utility helpers.
17 #include <corerror.h>
18 #include "ndpversion.h"
19 #include "../dlls/mscorrc/resource.h"
20 #include "ex.h"
21 #if !defined(FEATURE_CORESYSTEM)
22 #undef NTDDI_VERSION
23 #define NTDDI_VERSION NTDDI_WIN7
24 #include "commctrl.h"
25 #endif
26
27
28 BOOL ShouldDisplayMsgBoxOnCriticalFailure()
29 {
30     CONTRACTL
31     {
32         NOTHROW;
33     }
34     CONTRACTL_END;
35
36 #ifdef _DEBUG
37     // To help find issues, we will always display dialogs for critical failures
38     // under debug builds. This includes asserts and other critical issues.
39    return TRUE;
40 #else      
41     // Retrieve error mode
42     UINT last = SetErrorMode(0);
43     SetErrorMode(last);         //set back to previous value
44                     
45     // SEM_FAILCRITICALERRORS indicates that the system does not display the critical-error-handler 
46     // message box. Instead, the system sends the error to the calling process.
47     return !(last & SEM_FAILCRITICALERRORS);
48 #endif // _DEBUG
49 }
50
51
52
53
54 // We'd like to use TaskDialogIndirect for asserts coming from managed code in particular
55 // to display the detailedText in a scrollable way.  Also, we'd like to reuse the CLR's
56 // plumbing code for the rest of parts of the assert dialog.  Note that the simple
57 // Win32 MessageBox does not support the detailedText value.
58 // If we later refactor MessageBoxImpl into its own DLL, move the lines referencing
59 // "Microsoft.Windows.Common-Controls" version 6 in stdafx.h as well.  
60 int MessageBoxImpl(
61                   HWND hWnd,            // Handle to Owner Window
62                   LPCWSTR message,      // Message
63                   LPCWSTR title,        // Dialog box title
64                   LPCWSTR detailedText, // Details like a stack trace, etc.
65                   UINT uType)
66 {
67     CONTRACTL
68     {
69         // May pump messages.  Callers should be GC_TRIGGERS and MODE_PREEMPTIVE,
70         // but we can't include EE contracts here.
71         THROWS;
72         INJECT_FAULT(return IDCANCEL;);
73
74         // Assert if none of MB_ICON is set
75         PRECONDITION((uType & MB_ICONMASK) != 0);
76     }
77     CONTRACTL_END;
78
79     return WszMessageBox(hWnd, message, title, uType);
80 }
81
82 int UtilMessageBoxVA(
83                   HWND hWnd,        // Handle to Owner Window
84                   UINT uText,       // Resource Identifier for Text message
85                   UINT uTitle,      // Resource Identifier for Title
86                   UINT uType,       // Style of MessageBox
87                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
88                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
89                   va_list args)     // Additional Arguments
90 {
91     CONTRACTL
92     {
93         NOTHROW;
94         INJECT_FAULT(return IDCANCEL;);
95     }
96     CONTRACTL_END;
97
98     SString text;
99     SString title; 
100     int result = IDCANCEL;
101     
102     EX_TRY
103     {
104         text.LoadResource(CCompRC::Error, uText);
105         title.LoadResource(CCompRC::Error, uTitle);
106
107         result = UtilMessageBoxNonLocalizedVA(hWnd, (LPWSTR)text.GetUnicode(), 
108             (LPWSTR)title.GetUnicode(), uType, displayForNonInteractive, showFileNameInTitle, NULL, args);
109     }
110     EX_CATCH
111     {
112         result = IDCANCEL;
113     }
114     EX_END_CATCH(SwallowAllExceptions);
115
116     return result;            
117 }
118
119 int UtilMessageBoxNonLocalizedVA(
120                   HWND hWnd,        // Handle to Owner Window
121                   LPCWSTR lpText,   // Text message
122                   LPCWSTR lpTitle,  // Title
123                   UINT uType,       // Style of MessageBox
124                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
125                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
126                   BOOL * pInputFromUser,            // To distinguish between user pressing abort vs. assuming abort.
127                   va_list args)     // Additional Arguments
128 {
129     CONTRACTL
130     {
131         NOTHROW;
132         INJECT_FAULT(return IDCANCEL;);
133
134         // Assert if none of MB_ICON is set
135         PRECONDITION((uType & MB_ICONMASK) != 0);
136     }
137     CONTRACTL_END;
138
139     return UtilMessageBoxNonLocalizedVA(hWnd, lpText, lpTitle, NULL, uType, displayForNonInteractive, showFileNameInTitle, pInputFromUser, args);
140 }
141
142 int UtilMessageBoxNonLocalizedVA(
143                   HWND hWnd,        // Handle to Owner Window
144                   LPCWSTR lpText,   // Text message
145                   LPCWSTR lpTitle,  // Title
146                   LPCWSTR lpDetails,// Details like a stack trace, etc.
147                   UINT uType,       // Style of MessageBox
148                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
149                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
150                   BOOL * pInputFromUser,            // To distinguish between user pressing abort vs. assuming abort.
151                   va_list args)     // Additional Arguments
152 {
153     CONTRACTL
154     {
155         NOTHROW;
156         INJECT_FAULT(return IDCANCEL;);
157
158         // Assert if none of MB_ICON is set
159         PRECONDITION((uType & MB_ICONMASK) != 0);
160     }
161     CONTRACTL_END;
162
163     int result = IDCANCEL;
164         if (pInputFromUser != NULL)
165         {
166         *pInputFromUser = FALSE;
167         }
168
169     EX_TRY
170     {   
171         StackSString formattedMessage;
172         StackSString formattedTitle;
173         SString details(lpDetails);
174         PathString fileName;
175         BOOL fDisplayMsgBox = TRUE;
176         
177         // Format message string using optional parameters
178         formattedMessage.VPrintf(lpText, args);
179        
180         // Try to get filename of Module and add it to title
181         if (showFileNameInTitle && WszGetModuleFileName(NULL, fileName))
182         {           
183             LPCWSTR wszName = NULL;
184             size_t cchName = 0;
185
186                   
187             
188             SplitPathInterior(fileName, NULL, NULL, NULL, NULL, &wszName, &cchName, NULL, NULL);
189             formattedTitle.Printf(W("%s - %s"), wszName, lpTitle);
190         }
191         else
192         {
193             formattedTitle.Set(lpTitle);
194         }
195
196 #if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES)
197         // If the current process isn't interactive (a service for example), then we report the message 
198         // in the event log and via OutputDebugString. 
199         // 
200         // We may still however attempt to display the message box if the MB_SERVICE_NOTIFICATION
201         // message box style was specified.
202         if (!RunningInteractive())
203         {
204             StackSString message;
205
206             message.Printf(W(".NET Runtime version : %s - "), VER_FILEVERSION_STR_L);
207             if (lpTitle)
208                 message.Append(lpTitle);
209             if (!formattedMessage.IsEmpty())
210                 message.Append(formattedMessage);
211
212             ClrReportEvent(W(".NET Runtime"),
213                 EVENTLOG_ERROR_TYPE,    // event type 
214                 0,                      // category zero
215                 1024,                   // event identifier
216                 NULL,                   // no user security identifier
217                 message.GetUnicode());
218             
219             if(lpTitle != NULL)
220                 WszOutputDebugString(lpTitle);
221             if(!formattedMessage.IsEmpty())
222                 WszOutputDebugString(formattedMessage);
223
224             // If we are running as a service and displayForNonInteractive is FALSE then IDABORT is 
225             // the best value to return as it will most likely cause callers of this API to abort the process. 
226             // This is the right thing to do since attaching a debugger doesn't make much sense when the process isn't
227             // running in interactive mode.
228             if(!displayForNonInteractive)   
229             {
230                 fDisplayMsgBox = FALSE;
231                 result = IDABORT;
232             }
233             else
234             {
235                 // Include in the MB_DEFAULT_DESKTOP_ONLY style.
236                 uType |= MB_DEFAULT_DESKTOP_ONLY;                            
237             }
238         }
239 #endif //!defined(FEATURE_UTILCODE_NO_DEPENDENCIES)
240
241         if (fDisplayMsgBox)
242         {
243             // We normally want to set the reading direction (right-to-left etc.) based on the resources
244             // in use.  However, outside the CLR (SELF_NO_HOST) we can't assume we have resources and
245             // in CORECLR we can't even necessarily expect that our CLR callbacks have been initialized.
246             // This code path is used for ASSERT dialogs.
247             
248             result = MessageBoxImpl(hWnd, formattedMessage, formattedTitle, details, uType);
249             
250             if (pInputFromUser != NULL)
251             {
252                 *pInputFromUser = TRUE;
253             }
254         }
255     }        
256     EX_CATCH
257     {
258         result = IDCANCEL;
259     }
260     EX_END_CATCH(SwallowAllExceptions);
261
262     return result;
263 }
264
265 int UtilMessageBox(
266                   HWND hWnd,        // Handle to Owner Window
267                   UINT uText,       // Resource Identifier for Text message
268                   UINT uTitle,      // Resource Identifier for Title
269                   UINT uType,       // Style of MessageBox
270                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
271                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
272                   ...)              // Additional Arguments
273 {
274     CONTRACTL
275     {
276         NOTHROW;
277     }
278     CONTRACTL_END;
279
280     va_list marker;
281     va_start(marker, showFileNameInTitle);
282
283     int result = UtilMessageBoxVA(hWnd, uText, uTitle, uType, displayForNonInteractive, showFileNameInTitle, marker);
284     va_end( marker );
285
286     return result;    
287 }
288
289 int UtilMessageBoxNonLocalized(
290                   HWND hWnd,        // Handle to Owner Window
291                   LPCWSTR lpText,   // Text message
292                   LPCWSTR lpTitle,  // Title message
293                   UINT uType,       // Style of MessageBox
294                   BOOL displayForNonInteractive,    // Display even if the process is running non interactive 
295                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
296                   ... )             // Additional Arguments
297 {
298     CONTRACTL
299     {
300         NOTHROW;
301     }
302     CONTRACTL_END;
303
304     va_list marker;
305     va_start(marker, showFileNameInTitle);
306
307     int result = UtilMessageBoxNonLocalizedVA(
308         hWnd, lpText, lpTitle, uType, displayForNonInteractive, showFileNameInTitle, NULL, marker);
309     va_end( marker );
310
311     return result;
312 }
313
314 int UtilMessageBoxCatastrophic(
315                   UINT uText,       // Text for MessageBox
316                   UINT uTitle,      // Title for MessageBox
317                   UINT uType,       // Style of MessageBox
318                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
319                   ...)
320 {
321     CONTRACTL
322     {
323         NOTHROW;
324     }
325     CONTRACTL_END;
326
327     va_list marker;
328     va_start(marker, showFileNameInTitle);
329
330     int result = UtilMessageBoxCatastrophicVA(uText, uTitle, uType, showFileNameInTitle, marker);
331     va_end( marker );
332
333     return result;
334 }
335
336 int UtilMessageBoxCatastrophicNonLocalized(
337                   LPCWSTR lpText,    // Text for MessageBox
338                   LPCWSTR lpTitle,   // Title for MessageBox
339                   UINT uType,        // Style of MessageBox
340                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
341                   ...)
342 {
343     CONTRACTL
344     {
345         NOTHROW;
346     }
347     CONTRACTL_END;
348
349     va_list marker;
350     va_start(marker, showFileNameInTitle);
351
352     int result = UtilMessageBoxCatastrophicNonLocalizedVA(lpText, lpTitle, uType, showFileNameInTitle, marker);
353     va_end( marker );
354
355     return result;
356 }
357
358 int UtilMessageBoxCatastrophicVA(
359                   UINT uText,       // Text for MessageBox
360                   UINT uTitle,      // Title for MessageBox
361                   UINT uType,       // Style of MessageBox
362                   BOOL showFileNameInTitle,         // Flag to show FileName in Caption
363                   va_list args)     // Additional Arguments
364 {
365     CONTRACTL
366     {
367         NOTHROW;
368     }
369     CONTRACTL_END;
370
371     HWND hwnd = NULL;
372
373     // We are already in a catastrophic situation so we can tolerate faults as well as GC mode violations to keep going. 
374     CONTRACT_VIOLATION(FaultNotFatal | GCViolation | ModeViolation);
375
376     if (!ShouldDisplayMsgBoxOnCriticalFailure())
377         return IDABORT;
378
379     // Add the MB_TASKMODAL style to indicate that the dialog should be displayed on top of the windows
380     // owned by the current thread and should prevent interaction with them until dismissed.
381     uType |= MB_TASKMODAL;
382
383     return UtilMessageBoxVA(hwnd, uText, uTitle, uType, TRUE, showFileNameInTitle, args);
384 }
385
386 int UtilMessageBoxCatastrophicNonLocalizedVA(
387                   LPCWSTR lpText,   // Text for MessageBox
388                   LPCWSTR lpTitle,  // Title for MessageBox
389                   UINT uType,       // Style of MessageBox
390                   BOOL showFileNameInTitle, // Flag to show FileName in Caption
391                   va_list args)     // Additional Arguments
392 {
393     CONTRACTL
394     {
395         NOTHROW;
396     }
397     CONTRACTL_END;
398
399     HWND hwnd = NULL;
400
401     // We are already in a catastrophic situation so we can tolerate faults as well as GC mode violations to keep going. 
402     CONTRACT_VIOLATION(FaultNotFatal | GCViolation | ModeViolation);
403
404     if (!ShouldDisplayMsgBoxOnCriticalFailure())
405         return IDABORT;
406
407     // Add the MB_TASKMODAL style to indicate that the dialog should be displayed on top of the windows
408     // owned by the current thread and should prevent interaction with them until dismissed.
409     uType |= MB_TASKMODAL;
410
411     return UtilMessageBoxNonLocalizedVA(hwnd, lpText, lpTitle, uType, TRUE, showFileNameInTitle, NULL, args);
412 }
413