more reliable error logging
This commit is contained in:
parent
c105f6700f
commit
49c4af8c2c
@ -4,9 +4,50 @@
|
|||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "../vnrhook/texthook.h"
|
#include "../vnrhook/texthook.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace
|
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
|
class ProcessRecord
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -96,6 +137,7 @@ namespace
|
|||||||
{
|
{
|
||||||
std::thread([]
|
std::thread([]
|
||||||
{
|
{
|
||||||
|
Host::Setup();
|
||||||
SECURITY_DESCRIPTOR pipeSD = {};
|
SECURITY_DESCRIPTOR pipeSD = {};
|
||||||
InitializeSecurityDescriptor(&pipeSD, SECURITY_DESCRIPTOR_REVISION);
|
InitializeSecurityDescriptor(&pipeSD, SECURITY_DESCRIPTOR_REVISION);
|
||||||
SetSecurityDescriptorDacl(&pipeSD, TRUE, NULL, FALSE); // Allow non-admin processes to connect to pipe created by admin host
|
SetSecurityDescriptorDacl(&pipeSD, TRUE, NULL, FALSE); // Allow non-admin processes to connect to pipe created by admin host
|
||||||
@ -146,6 +188,7 @@ namespace
|
|||||||
{
|
{
|
||||||
std::thread([]
|
std::thread([]
|
||||||
{
|
{
|
||||||
|
Host::Setup();
|
||||||
for (std::wstring last; true; Sleep(50))
|
for (std::wstring last; true; Sleep(50))
|
||||||
if (auto text = Util::GetClipboardText())
|
if (auto text = Util::GetClipboardText())
|
||||||
if (last != text.value())
|
if (last != text.value())
|
||||||
@ -156,6 +199,17 @@ namespace
|
|||||||
|
|
||||||
namespace Host
|
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)
|
void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onDestroy, TextThread::OutputCallback output)
|
||||||
{
|
{
|
||||||
OnAttach = onAttach; OnDetach = onDetach; OnCreate = onCreate; OnDestroy = onDestroy; TextThread::Output = 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
|
namespace Host
|
||||||
{
|
{
|
||||||
|
void Setup();
|
||||||
void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onDestroy, TextThread::OutputCallback output);
|
void Start(ProcessEventCallback onAttach, ProcessEventCallback onDetach, ThreadEventCallback onCreate, ThreadEventCallback onDestroy, TextThread::OutputCallback output);
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
@ -3,7 +3,14 @@
|
|||||||
#include "host.h"
|
#include "host.h"
|
||||||
#include "util.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()
|
TextThread::~TextThread()
|
||||||
{
|
{
|
||||||
|
@ -37,8 +37,7 @@ private:
|
|||||||
std::mutex bufferMutex;
|
std::mutex bufferMutex;
|
||||||
std::wstring storage;
|
std::wstring storage;
|
||||||
std::mutex storageMutex;
|
std::mutex storageMutex;
|
||||||
|
HANDLE deletionEvent;
|
||||||
HANDLE deletionEvent = CreateEventW(nullptr, FALSE, FALSE, NULL);
|
std::thread flushThread;
|
||||||
std::thread flushThread = std::thread([&] { while (WaitForSingleObject(deletionEvent, 10) == WAIT_TIMEOUT) Flush(); });
|
DWORD lastPushTime;
|
||||||
DWORD lastPushTime = GetTickCount();
|
|
||||||
};
|
};
|
||||||
|
41
GUI/main.cpp
41
GUI/main.cpp
@ -1,45 +1,14 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "host/host.h"
|
||||||
|
#include "misc.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <QApplication>
|
#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[])
|
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);
|
QApplication a(argc, argv);
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
w.show();
|
w.show();
|
||||||
|
Loading…
Reference in New Issue
Block a user