Print stack traces on SEH exceptions on Windows

Also tidies up a couple of things:
- Prevent handling of stack overflows, which cannot be done safely
- `exception_code` is a macro, so we rename it
- The `std::string` heap allocation was unnecessary

Fixes #4298

PiperOrigin-RevId: 544117790
Change-Id: I8ba61f87119d5fbdb1f653700d9867ca6f8c28ce
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc
index d1eddf1..704e1ac 100644
--- a/googletest/src/gtest.cc
+++ b/googletest/src/gtest.cc
@@ -866,7 +866,7 @@
 // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
 // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
 // This function is useful as an __except condition.
-int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+int UnitTestOptions::GTestShouldProcessSEH(DWORD seh_code) {
   // Google Test should handle a SEH exception if:
   //   1. the user wants it to, AND
   //   2. this is not a breakpoint exception, AND
@@ -881,9 +881,11 @@
 
   if (!GTEST_FLAG_GET(catch_exceptions))
     should_handle = false;
-  else if (exception_code == EXCEPTION_BREAKPOINT)
+  else if (seh_code == EXCEPTION_BREAKPOINT)
     should_handle = false;
-  else if (exception_code == kCxxExceptionCode)
+  else if (seh_code == EXCEPTION_STACK_OVERFLOW)
+    should_handle = false;
+  else if (seh_code == kCxxExceptionCode)
     should_handle = false;
 
   return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
@@ -2555,17 +2557,12 @@
 
 #if GTEST_HAS_SEH
 
-// Adds an "exception thrown" fatal failure to the current test.  This
-// function returns its result via an output parameter pointer because VC++
-// prohibits creation of objects with destructors on stack in functions
-// using __try (see error C2712).
-static std::string* FormatSehExceptionMessage(DWORD exception_code,
-                                              const char* location) {
+static std::string FormatSehExceptionMessage(DWORD exception_code,
+                                             const char* location) {
   Message message;
   message << "SEH exception with code 0x" << std::setbase(16) << exception_code
           << std::setbase(10) << " thrown in " << location << ".";
-
-  return new std::string(message.GetString());
+  return message.GetString();
 }
 
 #endif  // GTEST_HAS_SEH
@@ -2613,14 +2610,20 @@
     return (object->*method)();
   } __except (internal::UnitTestOptions::GTestShouldProcessSEH(  // NOLINT
       GetExceptionCode())) {
-    // We create the exception message on the heap because VC++ prohibits
-    // creation of objects with destructors on stack in functions using __try
+    // We wrap an inner function because VC++ prohibits direct creation of
+    // objects with destructors on stack in functions using __try
     // (see error C2712).
-    std::string* exception_message =
-        FormatSehExceptionMessage(GetExceptionCode(), location);
-    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
-                                             *exception_message);
-    delete exception_message;
+    struct Wrapper {
+      static void ReportFailure(DWORD code, const char* location) {
+        return internal::ReportFailureInUnknownLocation(
+            TestPartResult::kFatalFailure,
+            FormatSehExceptionMessage(code, location) +
+                "\n"
+                "Stack trace:\n" +
+                ::testing::internal::GetCurrentOsStackTraceExceptTop(1));
+      }
+    };
+    Wrapper::ReportFailure(GetExceptionCode(), location);
     return static_cast<Result>(0);
   }
 #else