Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
StructuredException.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#if qStroika_Foundation_Common_Platform_Windows
7#include <Windows.h>
8#else
9#error "WINDOWS REQUIRED FOR THIS MODULE"
10#endif
11
14#include "Stroika/Foundation/Common/Common.h"
16#include "Stroika/Foundation/Containers/Common.h"
18#include "Stroika/Foundation/Execution/Exceptions.h"
20
21#include "StructuredException.h"
22
23using namespace Stroika::Foundation;
25using namespace Stroika::Foundation::Debug;
26using namespace Stroika::Foundation::Execution;
27using namespace Stroika::Foundation::Execution::Platform;
29
30namespace {
31 class StructuredException_error_category_ : public error_category {
32 public:
33 virtual const char* name () const noexcept override
34 {
35 return "Windows Structured Exception error";
36 }
37 virtual error_condition default_error_condition ([[maybe_unused]] int ev) const noexcept override
38 {
39 // @todo - not sure how todo this - except by defining new conditions
40 //switch (ev) {
41 //}
42 return error_condition{errc::bad_message}; // no idea what to return here
43 }
44 virtual string message (int u) const override
45 {
46 switch (u) {
47 case EXCEPTION_ACCESS_VIOLATION:
48 return "EXCEPTION_ACCESS_VIOLATION";
49 case EXCEPTION_DATATYPE_MISALIGNMENT:
50 return "EXCEPTION_DATATYPE_MISALIGNMENT";
51 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
52 return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
53 case EXCEPTION_FLT_DENORMAL_OPERAND:
54 return "EXCEPTION_FLT_DENORMAL_OPERAND";
55 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
56 return "EXCEPTION_FLT_DENORMAL_OPERAND";
57 case EXCEPTION_FLT_INEXACT_RESULT:
58 return "EXCEPTION_FLT_INEXACT_RESULT";
59 case EXCEPTION_FLT_INVALID_OPERATION:
60 return "EXCEPTION_FLT_INVALID_OPERATION";
61 case EXCEPTION_FLT_OVERFLOW:
62 return "EXCEPTION_FLT_OVERFLOW";
63 case EXCEPTION_FLT_STACK_CHECK:
64 return "EXCEPTION_FLT_STACK_CHECK";
65 case EXCEPTION_FLT_UNDERFLOW:
66 return "EXCEPTION_FLT_UNDERFLOW";
67 case EXCEPTION_INT_DIVIDE_BY_ZERO:
68 return "EXCEPTION_INT_DIVIDE_BY_ZERO";
69 case EXCEPTION_INT_OVERFLOW:
70 return "EXCEPTION_INT_OVERFLOW";
71 case EXCEPTION_PRIV_INSTRUCTION:
72 return "EXCEPTION_PRIV_INSTRUCTION";
73 case EXCEPTION_IN_PAGE_ERROR:
74 return "EXCEPTION_IN_PAGE_ERROR";
75 case EXCEPTION_ILLEGAL_INSTRUCTION:
76 return "EXCEPTION_ILLEGAL_INSTRUCTION";
77 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
78 return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
79 case EXCEPTION_STACK_OVERFLOW:
80 return "EXCEPTION_STACK_OVERFLOW";
81 case EXCEPTION_INVALID_DISPOSITION:
82 return "EXCEPTION_INVALID_DISPOSITION";
83 case EXCEPTION_GUARD_PAGE:
84 return "EXCEPTION_GUARD_PAGE";
85 case EXCEPTION_INVALID_HANDLE:
86 return "EXCEPTION_INVALID_HANDLE";
87 default: {
88 char buf[1024];
89 (void)::snprintf (buf, Memory::NEltsOf (buf), "#0x%x", u);
90 return buf;
91 }
92 }
93 }
94 };
95}
96
97/*
98 ********************************************************************************
99 *********** Platform::Windows::StructuredException_error_category **************
100 ********************************************************************************
101 */
103{
104 return Common::Immortalize<StructuredException_error_category_> ();
105}
106
107namespace {
108 void trans_func_ (unsigned int u, EXCEPTION_POINTERS* pExp)
109 {
110 TraceContextBumper ctx{"{}::trans_func_"};
111 {
112 using namespace Characters::Literals;
113 // I wish I knew how to get a PROCNAME of where the caller was...
114 DbgTrace ("u = 0x{:x} ({})"_f, u, String::FromNarrowSDKString (StructuredException_error_category ().message (u)));
115 if (pExp != nullptr) {
116 if (pExp->ContextRecord != nullptr) {
117 TraceContextBumper ctx1{"ContextRecord"};
118 DbgTrace ("ContextRecord->ContextFlags = 0x{:x}"_f, pExp->ContextRecord->ContextFlags);
119 DbgTrace ("ContextRecord->Dr0 = 0x{:x}"_f, pExp->ContextRecord->Dr0);
120#if qStroika_Foundation_Common_Platform_Win32
121 DbgTrace ("ContextRecord->Esp = 0x{:x}"_f, pExp->ContextRecord->Esp);
122#endif
123 }
124 if (pExp->ExceptionRecord != nullptr) {
125 TraceContextBumper ctx1{"ExceptionRecord"};
126 DbgTrace ("ExceptionRecord->ExceptionAddress = 0x{:x}"_f, pExp->ExceptionRecord->ExceptionAddress);
127 DbgTrace ("ExceptionRecord->ExceptionCode = 0x{:x}"_f, pExp->ExceptionRecord->ExceptionCode);
128 DbgTrace ("ExceptionRecord->ExceptionFlags = 0x{:x}"_f, pExp->ExceptionRecord->ExceptionFlags);
129 DbgTrace ("ExceptionRecord->NumberParameters = {}"_f, pExp->ExceptionRecord->NumberParameters);
130 }
131 }
132 }
133 DbgTrace ("Translating it into a Platform::Windows::StructuredException::THROW()"_f);
134 Assert (false); // in case debug turned on, helpful to drop into the debugger here!
136 }
137}
138
139/*
140 ********************************************************************************
141 ******** Platform::Windows::RegisterDefaultHandler_StructuredException *********
142 ********************************************************************************
143 */
145{
146 DISABLE_COMPILER_MSC_WARNING_START (4535) // disable warning cuz MSVC appears to offer no way to check if this function is available, and harmless to register if not available
147 _set_se_translator (trans_func_);
148 DISABLE_COMPILER_MSC_WARNING_END (4535)
149}
#define DbgTrace
Definition Trace.h:309
const std::error_category & StructuredException_error_category() noexcept
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43