reactos/base/applications/drwtsn32/drwtsn32.cpp
William Kent 1d10606fad
[DRWTSN32] Various improvements
* Convert to wWinMain()
* Add a resource file
* Use a slightly friendlier application name
* Add code to load the output path from the Registry
* Add localized string resources
2018-03-10 00:04:57 +01:00

159 lines
4.4 KiB
C++

/*
* PROJECT: Dr. Watson crash reporter
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Debug loop
* COPYRIGHT: Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
*/
#include "precomp.h"
#include <psapi.h>
#define MS_VC_EXCEPTION_THREAD_NAME 0x406d1388
ModuleData::ModuleData(void* addr)
{
BaseAddress = addr;
Size = 0;
Unloaded = false;
}
void ModuleData::Update(HANDLE hProcess)
{
MODULEINFO mi = {0};
GetModuleInformation(hProcess, (HMODULE)BaseAddress, &mi, sizeof(mi));
assert(BaseAddress == mi.lpBaseOfDll);
Size = mi.SizeOfImage;
ModuleName.resize(MAX_PATH);
DWORD dwLen = GetModuleFileNameExA(hProcess, (HMODULE)BaseAddress, &ModuleName[0], ModuleName.size());
ModuleName.resize(dwLen);
}
ThreadData::ThreadData(HANDLE handle)
: Handle(handle)
{
memset(&Context, 0, sizeof(Context));
}
void ThreadData::Update()
{
Context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(Handle, &Context);
}
DumpData::DumpData()
:ProcessID(0)
,ThreadID(0)
,ProcessHandle(NULL)
,Event(NULL)
,FirstBPHit(false)
{
memset(&ExceptionInfo, 0, sizeof(ExceptionInfo));
}
bool UpdateFromEvent(DEBUG_EVENT& evt, DumpData& data)
{
switch(evt.dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT:
{
data.ProcessPath.resize(MAX_PATH*2);
DWORD len = GetModuleFileNameExW(evt.u.CreateProcessInfo.hProcess, NULL, &data.ProcessPath[0], data.ProcessPath.size());
if (len)
{
data.ProcessPath.resize(len);
std::string::size_type pos = data.ProcessPath.find_last_of(L"\\/");
if (pos != std::string::npos)
data.ProcessName = data.ProcessPath.substr(pos+1);
}
else
{
data.ProcessPath = L"??";
}
if (data.ProcessName.empty())
data.ProcessName = data.ProcessPath;
CloseHandle(evt.u.CreateProcessInfo.hFile);
data.ProcessID = evt.dwProcessId;
data.ProcessHandle = evt.u.CreateProcessInfo.hProcess;
data.Threads[evt.dwThreadId] = ThreadData(evt.u.CreateProcessInfo.hThread);
}
break;
case CREATE_THREAD_DEBUG_EVENT:
data.Threads[evt.dwThreadId] = ThreadData(evt.u.CreateThread.hThread);
break;
case EXIT_THREAD_DEBUG_EVENT:
{
ThreadMap::iterator it = data.Threads.find(evt.dwThreadId);
if (it != data.Threads.end())
{
data.Threads.erase(it);
}
}
break;
case LOAD_DLL_DEBUG_EVENT:
CloseHandle(evt.u.LoadDll.hFile);
for (size_t n = 0; n < data.Modules.size(); ++n)
{
if (data.Modules[n].BaseAddress == evt.u.LoadDll.lpBaseOfDll)
{
data.Modules[n].Unloaded = false;
return true;
}
}
data.Modules.push_back(ModuleData(evt.u.LoadDll.lpBaseOfDll));
break;
case UNLOAD_DLL_DEBUG_EVENT:
for (size_t n = 0; n < data.Modules.size(); ++n)
{
if (data.Modules[n].BaseAddress == evt.u.UnloadDll.lpBaseOfDll)
data.Modules[n].Unloaded = true;
}
break;
case OUTPUT_DEBUG_STRING_EVENT: // ignore
break;
case EXCEPTION_DEBUG_EVENT:
if (evt.u.Exception.dwFirstChance)
{
switch(evt.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
if (!data.FirstBPHit)
{
data.FirstBPHit = true;
if (data.Event)
{
SetEvent(data.Event);
CloseHandle(data.Event);
data.Event = NULL;
}
return true;
}
break;
case MS_VC_EXCEPTION_THREAD_NAME:
/* Thread name */
return true;
case DBG_CONTROL_C:
case DBG_CONTROL_BREAK:
return true;
}
}
data.ExceptionInfo = evt.u.Exception;
data.ThreadID = evt.dwThreadId;
return false;
case EXIT_PROCESS_DEBUG_EVENT:
//assert(FALSE);
return false;
case RIP_EVENT:
//assert(FALSE);
return false;
default:
assert(false);
}
return true;
}