windows-app-bootstrap.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2015 Intel Corporation. All Rights Reserved.
3 
4 // This file converts the call to WinMain to a call to cross-platform main
5 // We need WinMain on Windows to offer proper Windows application and not console application
6 // Should not be used in CMake on Linux
7 
8 
9 #include <Windows.h>
10 #include <memory>
11 #include <vector>
12 #include <algorithm>
13 #include <iterator>
14 #include <sstream>
15 #include <iostream>
16 #include <csignal>
17 
18 #include "os.h"
19 #include "metadata-helper.h"
20 #include "rendering.h"
21 #include <delayimp.h>
22 
23 // Use OS hook to modify message box behaviour
24 // This lets us implement "report" functionality if Viewer is crashing
25 HHOOK hhk;
26 // When launching messagebox, replace standard Cancel button with "report"
27 LRESULT CALLBACK cbtproc(INT code, WPARAM wParam, LPARAM lParam)
28 {
29  HWND window = (HWND)wParam;
30  if (code == HCBT_ACTIVATE)
31  {
32  if (GetDlgItem(window, IDCANCEL) != NULL)
33  {
34  SetDlgItemText(window, IDCANCEL, L"Report");
35  }
36  UnhookWindowsHookEx(hhk);
37  }
38  else CallNextHookEx(hhk, code, wParam, lParam);
39  return 0;
40 }
41 
42 bool should_intercept(int code)
43 {
44  if (code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP) return false;
45  return true;
46 }
47 
48 std::string exception_code_to_string(int code, struct _EXCEPTION_POINTERS *ep)
49 {
50  if (code == EXCEPTION_ACCESS_VIOLATION) return "Access Violation!";
51  else if (code == EXCEPTION_ARRAY_BOUNDS_EXCEEDED) return "Array out of bounds access error!";
52  else if (code == EXCEPTION_DATATYPE_MISALIGNMENT) return "Read / write of misaligned data!";
53  else if (code == EXCEPTION_FLT_DENORMAL_OPERAND) return "Denormal floating point operation!";
54  else if (code == EXCEPTION_FLT_DIVIDE_BY_ZERO) return "Unhandled floating point division by zero!";
55  else if (code == EXCEPTION_FLT_INEXACT_RESULT) return "Inexact floating point result!";
56  else if (code == EXCEPTION_FLT_INVALID_OPERATION) return "Invalid floating point operation!";
57  else if (code == EXCEPTION_FLT_OVERFLOW) return "Floating point overflow!";
58  else if (code == EXCEPTION_FLT_STACK_CHECK) return "Floating point stack overflow / underflow!";
59  else if (code == EXCEPTION_FLT_UNDERFLOW) return "Floating point underflow!";
60  else if (code == EXCEPTION_ILLEGAL_INSTRUCTION) return "Illegal CPU instruction!\nPossibly newer CPU architecture is required";
61  else if (code == EXCEPTION_IN_PAGE_ERROR) return "In page error!\nPossibly network connection error when running the program over network";
62  else if (code == EXCEPTION_INT_DIVIDE_BY_ZERO) return "Unhandled integer division by zero!";
63  else if (code == EXCEPTION_INT_OVERFLOW) return "Integer overflow!";
64  else if (code == EXCEPTION_INVALID_DISPOSITION) return "Invalid disposition error!";
65  else if (code == EXCEPTION_NONCONTINUABLE_EXCEPTION) return "Noncontinuable exception occured!";
66  else if (code == EXCEPTION_PRIV_INSTRUCTION) return "Error due to invalid call to priviledged instruction!";
67  else if (code == EXCEPTION_STACK_OVERFLOW) return "Stack overflow error!";
68  else if (code == VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)) {
69  auto details = (DelayLoadInfo*)ep->ExceptionRecord->ExceptionInformation[0];
70  std::string dll_name = details->szDll;
71  std::string fname = details->dlp.szProcName;
72  return rs2::to_string() << "Could not find " << dll_name << " library required for " << fname << ".\nMake sure all program dependencies are reachable or download standalone version of the App from our GitHub";
73  }
74  else return rs2::to_string() << "Unknown error (" << code << ")!";
75 }
76 
77 // Show custom error message box with OK and Report options
78 // Report will prompt new GitHub issue
80 {
81  std::wstring ws(error.begin(), error.end());
82  SetWindowsHookEx(WH_CBT, &cbtproc, 0, GetCurrentThreadId());
83  auto button = MessageBox(NULL, ws.c_str(), L"Something went wrong...", MB_ICONERROR | MB_OKCANCEL);
84  if (button == IDCANCEL)
85  {
86  std::stringstream ss;
87  rs2_error* e = nullptr;
88 
89  ss << "| | |\n";
90  ss << "|---|---|\n";
91  ss << "|**librealsense**|" << rs2::api_version_to_string(rs2_get_api_version(&e)) << (rs2::is_debug() ? " DEBUG" : " RELEASE") << "|\n";
92  ss << "|**OS**|" << rs2::get_os_name() << "|\n\n";
93  ss << "Intel RealSense Viewer / Depth Quality Tool has crashed with the following error message:\n";
94  ss << "```\n";
95  ss << error;
96  ss << "\n```";
97 
98  std::string link = "https://github.com/IntelRealSense/librealsense/issues/new?body=" + rs2::url_encode(ss.str());
99  rs2::open_url(link.c_str());
100  }
101 }
102 
103 // Global crash handler will be triggered when exception escapes from thread
104 LONG WINAPI CrashHandler(EXCEPTION_POINTERS* ep)
105 {
106  auto code = ep->ExceptionRecord->ExceptionCode;
107 
108  if (should_intercept(code))
109  {
110  std::string error = "Unhandled exception escaping from a worker thread!\nError type: ";
111  error += exception_code_to_string(code, ep);
112  report_error(error);
113  }
114 
115  return EXCEPTION_CONTINUE_SEARCH;
116 }
117 
118 // Actual main - implemented in the cross-platform section of the App
119 int main(int argv, const char** argc);
120 
121 int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
122 {
123  if (should_intercept(code))
124  {
125  auto error = exception_code_to_string(code, ep);
126  std::cerr << "Program terminated due to an unrecoverable SEH exception:\n" << error;
127  return EXCEPTION_EXECUTE_HANDLER;
128  }
129  else return EXCEPTION_CONTINUE_SEARCH;
130 }
131 
132 // Wrapper around main. Must be in a function without destructors (that does not require stack unwinding)
133 int run_main(int argv, const char** argc)
134 {
135  SetUnhandledExceptionFilter(CrashHandler);
136 
137  int res = 0;
138  __try
139  {
140  res = main(argv, argc);
141  }
142  __except (filter(GetExceptionCode(), GetExceptionInformation()))
143  {
144  res = EXIT_FAILURE;
145  }
146  return res;
147 }
148 
149 int CALLBACK WinMain(
150  _In_ HINSTANCE hInstance,
151  _In_ HINSTANCE hPrevInstance,
152  _In_ LPSTR lpCmdLine,
153  _In_ int nCmdShow
154 )
155 {
156  int argCount;
157 
158  std::shared_ptr<LPWSTR> szArgList(CommandLineToArgvW(GetCommandLine(), &argCount), LocalFree);
159  if (szArgList == NULL) return main(0, nullptr);
160 
161  std::vector<std::string> args;
162  for (int i = 0; i < argCount; i++)
163  {
164  std::wstring ws = szArgList.get()[i];
165  std::string s(ws.begin(), ws.end());
166 
168  {
169  try
170  {
172  exit(0);
173  }
174  catch (...) { exit(-1); }
175  }
176 
177  args.push_back(s);
178  }
179 
180  std::vector<const char*> argc;
181  std::transform(args.begin(), args.end(), std::back_inserter(argc), [](const std::string& s) { return s.c_str(); });
182 
183  // Redirect CERR to string stream
184  std::stringstream ss;
185  std::cerr.rdbuf(ss.rdbuf());
186 
187  int res = run_main(static_cast<int>(argc.size()), argc.data());
188 
189  if (res == EXIT_FAILURE)
190  {
191  report_error(ss.str());
192  }
193 
194  return res;
195 }
std::string exception_code_to_string(int code, struct _EXCEPTION_POINTERS *ep)
int rs2_get_api_version(rs2_error **error)
Definition: rs.cpp:1184
GLdouble s
static std::string get_command_line_param()
HHOOK hhk
int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
static metadata_helper & instance()
GLsizei const GLchar *const * string
bool is_debug()
Definition: os.cpp:368
e
Definition: rmse.py:177
virtual void enable_metadata()
static const textual_icon link
Definition: model-views.h:257
void open_url(const char *url)
Definition: os.cpp:58
std::string url_encode(const std::string &value)
Definition: os.cpp:381
bool should_intercept(int code)
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
static const textual_icon exit
Definition: model-views.h:254
LONG WINAPI CrashHandler(EXCEPTION_POINTERS *ep)
LRESULT CALLBACK cbtproc(INT code, WPARAM wParam, LPARAM lParam)
fname
Definition: rmse.py:13
void report_error(std::string error)
std::string api_version_to_string(int version)
Definition: rendering.h:1590
std::ostream & cerr()
#define NULL
Definition: tinycthread.c:47
int main(int argv, const char **argc)
int i
GLuint res
Definition: glext.h:8856
GLuint GLenum GLenum transform
Definition: glext.h:11553
int run_main(int argv, const char **argc)
std::string get_os_name()
Definition: os.cpp:351
std::string to_string(T value)


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:50:23