forked from Public-Mirror/Textractor
more reliable error logging
This commit is contained in:
parent
c105f6700f
commit
49c4af8c2c
@ -4,9 +4,50 @@
|
||||
#include "defs.h"
|
||||
#include "util.h"
|
||||
#include "../vnrhook/texthook.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace
|
||||
{
|
||||
char* GetCppExceptionInfo(EXCEPTION_POINTERS* exception)
|
||||
{
|
||||
// See https://blogs.msdn.microsoft.com/oldnewthing/20100730-00/?p=13273
|
||||
// Not very reliable so use __try
|
||||
__try { return ((char****)exception->ExceptionRecord->ExceptionInformation[2])[3][1][1] + 8; }
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) { return "Could not find"; }
|
||||
}
|
||||
|
||||
std::wstring lastError = L"Unknown error";
|
||||
|
||||
LONG WINAPI ExceptionLogger(EXCEPTION_POINTERS* exception)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION info = {};
|
||||
VirtualQuery(exception->ExceptionRecord->ExceptionAddress, &info, sizeof(info));
|
||||
wchar_t moduleName[MAX_PATH] = {};
|
||||
GetModuleFileNameW((HMODULE)info.AllocationBase, moduleName, MAX_PATH);
|
||||
|
||||
std::wstringstream errorMsg;
|
||||
errorMsg << std::uppercase << std::hex <<
|
||||
L"Error code: " << exception->ExceptionRecord->ExceptionCode << std::endl <<
|
||||
L"Error address: " << (uint64_t)exception->ExceptionRecord->ExceptionAddress << std::endl <<
|
||||
L"Error in module: " << moduleName << std::endl;
|
||||
|
||||
if (exception->ExceptionRecord->ExceptionCode == 0xE06D7363)
|
||||
errorMsg << L"Additional info: " << GetCppExceptionInfo(exception) << std::endl;
|
||||
|
||||
for (int i = 0; i < exception->ExceptionRecord->NumberParameters; ++i)
|
||||
errorMsg << L"Additional info: " << exception->ExceptionRecord->ExceptionInformation[i] << std::endl;
|
||||
|
||||
lastError = errorMsg.str();
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
void Terminate()
|
||||
{
|
||||
MessageBoxW(NULL, lastError.c_str(), L"Textractor ERROR", MB_ICONERROR);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
class ProcessRecord
|
||||
{
|
||||
public:
|
||||
@ -96,6 +137,7 @@ namespace
|
||||
{
|
||||
std::thread([]
|
||||
{
|
||||
Host::Setup();
|
||||
SECURITY_DESCRIPTOR pipeSD = {};
|
||||
InitializeSecurityDescriptor(&pipeSD, SECURITY_DESCRIPTOR_REVISION);
|
||||
SetSecurityDescriptorDacl(&pipeSD, TRUE, NULL, FALSE); // Allow non-admin processes to connect to pipe created by admin host
|
||||
@ -146,6 +188,7 @@ namespace
|
||||
{
|
||||
std::thread([]
|
||||
{
|
||||
Host::Setup();
|
||||
for (std::wstring last; true; Sleep(50))
|
||||
if (auto text = Util::GetClipboardText())
|
||||
if (last != text.value())
|
||||
@ -156,6 +199,17 @@ namespace
|
||||
|
||||
namespace Host
|
||||
{
|
||||
void Setup()
|
||||
{
|
||||
static std::once_flag flag;
|
||||
std::call_once(flag, []
|
||||
{
|
||||
AddVectoredExceptionHandler(FALSE, ExceptionLogger);
|
||||
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)Terminate);
|
||||
});
|
||||
std::set_terminate(Terminate);
|
||||
}
|
||||
|
||||
void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onDestroy, TextThread::OutputCallback output)
|
||||
{
|
||||
OnAttach = onAttach; OnDetach = onDetach; OnCreate = onCreate; OnDestroy = onDestroy; TextThread::Output = output;
|
||||
|
@ -8,6 +8,7 @@ typedef std::function<void(std::shared_ptr<TextThread>)> ThreadEventCallback;
|
||||
|
||||
namespace Host
|
||||
{
|
||||
void Setup();
|
||||
void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onDestroy, TextThread::OutputCallback output);
|
||||
void Close();
|
||||
|
||||
|
@ -3,7 +3,14 @@
|
||||
#include "host.h"
|
||||
#include "util.h"
|
||||
|
||||
TextThread::TextThread(ThreadParam tp, HookParam hp, std::wstring name) : handle(threadCounter++), name(name), tp(tp), hp(hp) {}
|
||||
TextThread::TextThread(ThreadParam tp, HookParam hp, std::wstring name) :
|
||||
handle(threadCounter++),
|
||||
name(name),
|
||||
tp(tp),
|
||||
hp(hp),
|
||||
deletionEvent(CreateEventW(nullptr, FALSE, FALSE, NULL)),
|
||||
flushThread([&] { Host::Setup(); while (WaitForSingleObject(deletionEvent, 10) == WAIT_TIMEOUT) Flush(); })
|
||||
{}
|
||||
|
||||
TextThread::~TextThread()
|
||||
{
|
||||
|
@ -37,8 +37,7 @@ private:
|
||||
std::mutex bufferMutex;
|
||||
std::wstring storage;
|
||||
std::mutex storageMutex;
|
||||
|
||||
HANDLE deletionEvent = CreateEventW(nullptr, FALSE, FALSE, NULL);
|
||||
std::thread flushThread = std::thread([&] { while (WaitForSingleObject(deletionEvent, 10) == WAIT_TIMEOUT) Flush(); });
|
||||
DWORD lastPushTime = GetTickCount();
|
||||
HANDLE deletionEvent;
|
||||
std::thread flushThread;
|
||||
DWORD lastPushTime;
|
||||
};
|
||||
|
41
GUI/main.cpp
41
GUI/main.cpp
@ -1,45 +1,14 @@
|
||||
#include "mainwindow.h"
|
||||
#include "host/host.h"
|
||||
#include "misc.h"
|
||||
#include <sstream>
|
||||
#include <QApplication>
|
||||
|
||||
namespace
|
||||
{
|
||||
char* GetCppExceptionInfo(EXCEPTION_POINTERS* exception)
|
||||
{
|
||||
// See https://blogs.msdn.microsoft.com/oldnewthing/20100730-00/?p=13273
|
||||
// Not very reliable so use __try
|
||||
__try { return ((char****)exception->ExceptionRecord->ExceptionInformation[2])[3][1][1] + 8; }
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) { return "Could not find"; }
|
||||
}
|
||||
|
||||
LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* exception)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION info = {};
|
||||
VirtualQuery(exception->ExceptionRecord->ExceptionAddress, &info, sizeof(info));
|
||||
wchar_t moduleName[MAX_PATH] = {};
|
||||
GetModuleFileNameW((HMODULE)info.AllocationBase, moduleName, MAX_PATH);
|
||||
|
||||
std::wstringstream errorMsg;
|
||||
errorMsg << std::uppercase << std::hex <<
|
||||
L"Error code: " << exception->ExceptionRecord->ExceptionCode << std::endl <<
|
||||
L"Error address: " << (uint64_t)exception->ExceptionRecord->ExceptionAddress << std::endl <<
|
||||
L"Error in module: " << moduleName << std::endl;
|
||||
|
||||
if (exception->ExceptionRecord->ExceptionCode == 0xE06D7363)
|
||||
errorMsg << L"Additional info: " << GetCppExceptionInfo(exception) << std::endl;
|
||||
|
||||
for (int i = 0; i < exception->ExceptionRecord->NumberParameters; ++i)
|
||||
errorMsg << L"Additional info: " << exception->ExceptionRecord->ExceptionInformation[i] << std::endl;
|
||||
|
||||
MessageBoxW(NULL, errorMsg.str().c_str(), L"Textractor ERROR", MB_ICONERROR);
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SetUnhandledExceptionFilter(ExceptionHandler);
|
||||
Host::Setup();
|
||||
QString exe = GetFullModuleName(GetCurrentProcessId());
|
||||
SetCurrentDirectoryW(exe.left(exe.lastIndexOf("\\")).toStdWString().c_str());
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
Loading…
x
Reference in New Issue
Block a user