winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Debugging.cpp (3201B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "Public/winget/Debugging.h"
      5 #include "Public/AppInstallerRuntime.h"
      6 #include "Public/AppInstallerDateTime.h"
      7 
      8 namespace AppInstaller::Debugging
      9 {
     10     namespace
     11     {
     12         constexpr std::string_view c_minidumpPrefix = "Minidump";
     13         constexpr std::string_view c_minidumpExtension = ".mdmp";
     14 
     15         struct SelfInitiatedMinidumpHelper
     16         {
     17             SelfInitiatedMinidumpHelper() : m_keepFile(false)
     18             {
     19                 m_filePath = Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation);
     20                 m_filePath /= c_minidumpPrefix.data() + ('-' + Utility::GetCurrentTimeForFilename() + c_minidumpExtension.data());
     21 
     22                 m_file.reset(CreateFile(m_filePath.wstring().c_str(), GENERIC_READ | GENERIC_WRITE,
     23                     FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr));
     24                 THROW_LAST_ERROR_IF(!m_file);
     25 
     26                 SetUnhandledExceptionFilter(UnhandledExceptionCallback);
     27             }
     28 
     29             ~SelfInitiatedMinidumpHelper()
     30             {
     31                 if (!m_keepFile)
     32                 {
     33                     m_file.reset();
     34                     DeleteFile(m_filePath.wstring().c_str());
     35                 }
     36             }
     37 
     38             static SelfInitiatedMinidumpHelper& Instance()
     39             {
     40                 static SelfInitiatedMinidumpHelper instance;
     41                 return instance;
     42             }
     43 
     44             static LONG WINAPI UnhandledExceptionCallback(EXCEPTION_POINTERS* ExceptionInfo)
     45             {
     46                 MINIDUMP_EXCEPTION_INFORMATION exceptionInformation{};
     47                 // The unhandled exception filter is executed in the context of the failing thread.
     48                 exceptionInformation.ThreadId = GetCurrentThreadId();
     49                 exceptionInformation.ExceptionPointers = ExceptionInfo;
     50                 exceptionInformation.ClientPointers = FALSE;
     51 
     52                 std::thread([&]() {
     53                     MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), Instance().m_file.get(), MiniDumpNormal, &exceptionInformation, nullptr, nullptr);
     54                     Instance().m_keepFile = true;
     55                 }).join();
     56 
     57                 return EXCEPTION_CONTINUE_SEARCH;
     58             }
     59 
     60             void WriteMinidump()
     61             {
     62                 std::thread([&]() {
     63                     MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), Instance().m_file.get(), MiniDumpNormal, nullptr, nullptr, nullptr);
     64                     Instance().m_keepFile = true;
     65                     }).join();
     66             }
     67 
     68         private:
     69             std::filesystem::path m_filePath;
     70             wil::unique_handle m_file;
     71             std::atomic_bool m_keepFile;
     72         };
     73     }
     74 
     75     void EnableSelfInitiatedMinidump()
     76     {
     77         // Force object creation and thus enabling of the crash detection.
     78         SelfInitiatedMinidumpHelper::Instance();
     79     }
     80 
     81     void WriteMinidump()
     82     {
     83         SelfInitiatedMinidumpHelper::Instance().WriteMinidump();
     84     }
     85 }