From 0a6a0452416ca76cc9e90f39999d44bd419d1014 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Thu, 1 Mar 2012 00:12:04 +0000 Subject: [PATCH] Experimental minidump writer for Win32. Kinda buggy but kinda works. Originally committed to SVN as r6528. --- devel/w32dumper/aegisub-w32dumper.vcxproj | 91 +++++ .../aegisub-w32dumper.vcxproj.filters | 32 ++ devel/w32dumper/resource.h | 19 + devel/w32dumper/w32dumper.aps | Bin 0 -> 34380 bytes devel/w32dumper/w32dumper.cpp | 329 ++++++++++++++++++ devel/w32dumper/w32dumper.rc | 105 ++++++ 6 files changed, 576 insertions(+) create mode 100644 devel/w32dumper/aegisub-w32dumper.vcxproj create mode 100644 devel/w32dumper/aegisub-w32dumper.vcxproj.filters create mode 100644 devel/w32dumper/resource.h create mode 100644 devel/w32dumper/w32dumper.aps create mode 100644 devel/w32dumper/w32dumper.cpp create mode 100644 devel/w32dumper/w32dumper.rc diff --git a/devel/w32dumper/aegisub-w32dumper.vcxproj b/devel/w32dumper/aegisub-w32dumper.vcxproj new file mode 100644 index 000000000..f164d3644 --- /dev/null +++ b/devel/w32dumper/aegisub-w32dumper.vcxproj @@ -0,0 +1,91 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {343E27E9-303B-4489-BAD7-1DDCD1C9552A} + Win32Proj + aegisubw32dumper + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + comctl32.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreaded + + + Windows + true + true + true + comctl32.lib;psapi.lib;dbghelp.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/devel/w32dumper/aegisub-w32dumper.vcxproj.filters b/devel/w32dumper/aegisub-w32dumper.vcxproj.filters new file mode 100644 index 000000000..cd1886511 --- /dev/null +++ b/devel/w32dumper/aegisub-w32dumper.vcxproj.filters @@ -0,0 +1,32 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/devel/w32dumper/resource.h b/devel/w32dumper/resource.h new file mode 100644 index 000000000..ef44b025c --- /dev/null +++ b/devel/w32dumper/resource.h @@ -0,0 +1,19 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by w32dumper.rc +// +#define IDD_W32DUMPER 101 +#define IDC_LOGLIST 1001 +#define IDC_SYSLINK1 1002 +#define IDC_DUMPFOLDERLINK 1002 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/devel/w32dumper/w32dumper.aps b/devel/w32dumper/w32dumper.aps new file mode 100644 index 0000000000000000000000000000000000000000..9c01377b527f57c5cbef8030dd3f846b3f6869ce GIT binary patch literal 34380 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 Xzr`0K&ZcjX$JVD`%Kh^HKDPc3uI5~) literal 0 HcmV?d00001 diff --git a/devel/w32dumper/w32dumper.cpp b/devel/w32dumper/w32dumper.cpp new file mode 100644 index 000000000..eb5f1abbd --- /dev/null +++ b/devel/w32dumper/w32dumper.cpp @@ -0,0 +1,329 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "resource.h" + + +std::wstring CanonicalFileName(std::wstring const &fn) +{ + DWORD bufsize = GetLongPathNameW(fn.c_str(), 0, 0); + wchar_t *fnbuf = (LPWSTR)malloc(sizeof(*fnbuf)*bufsize); + bufsize = GetLongPathNameW(fn.c_str(), fnbuf, bufsize); + auto canfn = std::wstring(fnbuf, fnbuf+bufsize); + free(fnbuf); + return canfn; +} + +std::wstring GetDumpfileFolder() +{ + std::wstring dumpfile_folder; + wchar_t appdata_folder[MAX_PATH+1] = {0}; + SHGetFolderPathW(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, appdata_folder); + dumpfile_folder = std::wstring(appdata_folder); + dumpfile_folder += L"\\Aegisub\\"; + if (CreateDirectoryW(dumpfile_folder.c_str(), 0) == 0 && GetLastError() == ERROR_PATH_NOT_FOUND) + return std::wstring(); // nowhere to write, somehow there is no %appdata% + dumpfile_folder += L"dumps\\"; + CreateDirectoryW(dumpfile_folder.c_str(), 0); + return dumpfile_folder; +} + +std::wstring IntToWstring(int n) +{ + wchar_t buf[16]; + swprintf_s(buf, L"%d", n); + return std::wstring(buf); +} + + +// DNM = Dumper Notify Message +#define DNM_COMPLETED (WM_APP + 0) +#define DNM_ERROR (WM_APP + 1) +#define DNM_DUMPSTARTED (WM_APP + 2) +#define DNM_DUMPFINISHED (WM_APP + 3) + + +// Data being passed to the worker thread +struct DumperThreadData { + HWND hwndDlg; + HINSTANCE hInstance; +}; + +// Miniclass to make sure the dialog gets sent a message when the thread ends, +// regardless of the reason or manner +struct EnsureDialogNotifiedOfThreadCompletion { + HWND hwnd; + EnsureDialogNotifiedOfThreadCompletion(HWND hwnd) : hwnd(hwnd) { } + ~EnsureDialogNotifiedOfThreadCompletion() + { + SendMessageW(hwnd, DNM_COMPLETED, 0, 0); + } + void error(int code, wchar_t const *message) + { + SendMessageW(hwnd, DNM_ERROR, (WPARAM)code, (LPARAM)message); + } +}; + +struct WindowsHandle { + HANDLE handle; + explicit WindowsHandle(HANDLE handle) : handle(handle) { } + ~WindowsHandle() { if (handle != 0) CloseHandle(handle); } + operator HANDLE() { return handle; } +}; + +// Thread that will actually find and make dumps of Aegisub processes +void __cdecl dumper_thread(void *data) +{ + DumperThreadData *dtd = static_cast(data); + + EnsureDialogNotifiedOfThreadCompletion completion_notify(dtd->hwndDlg); + + // Find Aegisub's install dir based on where we are located + std::wstring aegisub_filename_prefix; + { + DWORD bufsize = MAX_PATH; + LPWSTR modfnbuf = (LPWSTR)malloc(sizeof(*modfnbuf)*bufsize); + DWORD modfnlen = GetModuleFileNameW(0, modfnbuf, bufsize); + if (modfnlen > bufsize) + { + bufsize = modfnlen; + modfnbuf = (LPWSTR)realloc(modfnbuf, sizeof(*modfnbuf)*bufsize); + modfnlen = GetModuleFileNameW(0, modfnbuf, bufsize); + } + aegisub_filename_prefix = CanonicalFileName(std::wstring(modfnbuf, modfnbuf+modfnlen)); + free(modfnbuf); + } + { + // Chomp it at the last backslash and append "aegisub" + size_t backslash_pos = aegisub_filename_prefix.rfind(L'\\'); + if (backslash_pos == std::wstring::npos) + { + completion_notify.error(2, L"Something is wrong with the installation path"); + return; + } + aegisub_filename_prefix.erase(backslash_pos+1); + } + + // Figure out where we should be writing dump files to + std::wstring dumpfile_folder = GetDumpfileFolder(); + if (dumpfile_folder.empty()) + { + completion_notify.error(3, L"Could not access folder for writing dump files to"); + return; + } + + // Get pids of all processes + std::vector process_ids; + { + size_t pidlist_size = 128; + size_t pidlist_count = 0; + do { + process_ids.resize(pidlist_size); + DWORD bytes_returned = 0; + if (EnumProcesses(&process_ids[0], sizeof(DWORD)*pidlist_size, &bytes_returned) == 0) + { + completion_notify.error(4, L"An error occurred trying to enumerate processes on the system"); + return; + } + pidlist_count = bytes_returned / sizeof(DWORD); + } while (pidlist_count == pidlist_size); + process_ids.resize(pidlist_count); + } + + // Build a string useful for making filenames more unique + std::wstring timestring; + { + time_t t = time(0); + tm curtime; + localtime_s(&curtime, &t); + wchar_t fmttime[20] = {0}; + swprintf_s(fmttime, L"%4d%02d%02d-%02d%02d%02d", + curtime.tm_year+1900, curtime.tm_mon, curtime.tm_mday, + curtime.tm_hour, curtime.tm_min, curtime.tm_sec); + timestring = std::wstring(fmttime); + } + + // Check each process for being interesting (i.e. probably an Aegisub process) + const DWORD mypid = GetCurrentProcessId(); + for (auto ppid = process_ids.begin(); ppid != process_ids.end(); ++ppid) + { + if (*ppid == mypid) + continue; + + WindowsHandle proc(OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, *ppid)); + if (proc == 0) + continue; + + // Get process name + std::wstring procfn; + { + DWORD bufsize = MAX_PATH; + LPWSTR modfnbuf = (LPWSTR)malloc(sizeof(*modfnbuf)*bufsize); + DWORD modfnlen = GetModuleFileNameExW(proc, 0, modfnbuf, bufsize); + if (modfnlen == 0) + { + DWORD err = GetLastError(); + continue; + } + if (modfnlen > bufsize) + { + bufsize = modfnlen; + modfnbuf = (LPWSTR)realloc(modfnbuf, sizeof(*modfnbuf)*bufsize); + modfnlen = GetModuleFileNameExW(proc, 0, modfnbuf, bufsize); + } + procfn = CanonicalFileName(std::wstring(modfnbuf, modfnbuf+modfnlen)); + free(modfnbuf); + } + + // Check it's relevant + if (procfn.find(aegisub_filename_prefix) != 0) + continue; + + // Pick a filename to write + std::wstring procfn_basename; + { + // Chop off everything up to and including last backslash + size_t pos = procfn.rfind(L'\\'); + if (pos != std::wstring::npos) + procfn_basename = procfn.substr(pos+1); + else + procfn_basename = procfn; + } + + // Tell about our exploits + SendMessageW(dtd->hwndDlg, DNM_DUMPSTARTED, (WPARAM)*ppid, (LPARAM)procfn_basename.c_str()); + + std::wstring dumpfile_name = + dumpfile_folder + + procfn_basename + L'-' + + IntToWstring(*ppid) + L'-' + + timestring + + L".dmp"; + + WindowsHandle dumpfile(CreateFileW(dumpfile_name.c_str(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)); + + MiniDumpWriteDump( + proc, + *ppid, + dumpfile, + MINIDUMP_TYPE(MiniDumpWithThreadInfo|MiniDumpIgnoreInaccessibleMemory|MiniDumpWithIndirectlyReferencedMemory), + 0, 0, 0); + + SendMessageW(dtd->hwndDlg, DNM_DUMPFINISHED, 0, (LPARAM)dumpfile_name.c_str()); + } +} + + +int numdumps = 0; +int numerrors = 0; + +void AddStringToListbox(HWND hwndDlg, std::wstring const &str) +{ + SendDlgItemMessageW(hwndDlg, IDC_LOGLIST, LB_ADDSTRING, 0, (LPARAM)str.c_str()); +} + +INT_PTR CALLBACK dialog_msghandler(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case DNM_COMPLETED: + EnableWindow(GetDlgItem(hwndDlg, IDCLOSE), TRUE); + if (numerrors > 0) + AddStringToListbox(hwndDlg, L"Finished with errors."); + else if (numdumps > 0) + AddStringToListbox(hwndDlg, std::wstring(L"Completed ") + IntToWstring(numdumps) + (numdumps>1?L" minidumps.":L" minidump.")); + else + AddStringToListbox(hwndDlg, L"Finished, found no processes to dump."); + break; + + case DNM_ERROR: + numerrors += 1; + AddStringToListbox(hwndDlg, std::wstring(L"An error occurred: ") + (wchar_t const *)lParam); + break; + + case DNM_DUMPSTARTED: + numdumps += 1; + AddStringToListbox(hwndDlg, std::wstring(L"Beginning dump of pid ") + IntToWstring(wParam) + L" (" + (wchar_t const *)lParam + L")"); + break; + + case DNM_DUMPFINISHED: + AddStringToListbox(hwndDlg, std::wstring(L" Finished dump: ") + (wchar_t const *)lParam); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDCLOSE: + if (HIWORD(wParam) == BN_CLICKED) + PostQuitMessage(0); + break; + } + break; + + case WM_NOTIFY: + { + NMHDR &nm = *(NMHDR*)lParam; + if (nm.idFrom == IDC_DUMPFOLDERLINK && (nm.code == NM_CLICK || nm.code == NM_RETURN)) + { + std::wstring dumpfile_folder = GetDumpfileFolder(); + ShellExecuteW(hwndDlg, L"open", dumpfile_folder.c_str(), 0, 0, SW_SHOWNORMAL); + } + } + break; + } + + return FALSE; +} + + +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' ""version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") + +int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + CoInitializeEx(0, COINIT_MULTITHREADED); + INITCOMMONCONTROLSEX iccx = { + sizeof(INITCOMMONCONTROLSEX), + ICC_LINK_CLASS|ICC_STANDARD_CLASSES + }; + if (InitCommonControlsEx(&iccx) == FALSE) + ExitProcess(1); + + HWND hwndDlg = CreateDialogW(hInstance, MAKEINTRESOURCE(IDD_W32DUMPER), 0, dialog_msghandler); + if (hwndDlg == 0) + ExitProcess(2); + + DumperThreadData dtd = { hwndDlg, hInstance }; + uintptr_t dumper_thread_handle = _beginthread(dumper_thread, 0, &dtd); + ShowWindow(hwndDlg, SW_SHOWNORMAL); + + MSG msg; + BOOL gmret; + while ((gmret = GetMessageW(&msg, 0, 0, 0)) != 0) + { + if (gmret == -1) + { + ExitProcess(3); + } + else if (!IsDialogMessageW(hwndDlg, &msg)) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + + CoUninitialize(); + + return gmret; +} diff --git a/devel/w32dumper/w32dumper.rc b/devel/w32dumper/w32dumper.rc new file mode 100644 index 000000000..ff1e67cbe --- /dev/null +++ b/devel/w32dumper/w32dumper.rc @@ -0,0 +1,105 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_W32DUMPER DIALOGEX 0, 0, 317, 118 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CAPTION +CAPTION "Aegisub crash logger" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Close",IDCLOSE,260,97,50,14,WS_DISABLED + LISTBOX IDC_LOGLIST,7,7,303,85,NOT LBS_NOTIFY | LBS_SORT | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + CONTROL "Open folder containing dump files",IDC_DUMPFOLDERLINK, + "SysLink",WS_TABSTOP,7,99,195,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_W32DUMPER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 310 + TOPMARGIN, 7 + BOTTOMMARGIN, 111 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (United Kingdom) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (United Kingdom) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED +