mirror of
https://github.com/reactos/reactos.git
synced 2025-05-28 13:38:19 +00:00
[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
This commit is contained in:
parent
2f548599a4
commit
1d10606fad
8 changed files with 133 additions and 38 deletions
|
@ -2,6 +2,7 @@
|
||||||
PROJECT(drwtsn32)
|
PROJECT(drwtsn32)
|
||||||
|
|
||||||
set_cpp(WITH_RUNTIME WITH_EXCEPTIONS WITH_STL)
|
set_cpp(WITH_RUNTIME WITH_EXCEPTIONS WITH_STL)
|
||||||
|
include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/atl)
|
||||||
|
|
||||||
list(APPEND CPP_SOURCE
|
list(APPEND CPP_SOURCE
|
||||||
drwtsn32.cpp
|
drwtsn32.cpp
|
||||||
|
@ -11,8 +12,9 @@ list(APPEND CPP_SOURCE
|
||||||
drwtsn32.h
|
drwtsn32.h
|
||||||
precomp.h)
|
precomp.h)
|
||||||
|
|
||||||
add_executable(drwtsn32 ${CPP_SOURCE})
|
add_executable(drwtsn32 ${CPP_SOURCE} drwtsn32.rc)
|
||||||
add_pch(drwtsn32 precomp.h CPP_SOURCE)
|
add_pch(drwtsn32 precomp.h CPP_SOURCE)
|
||||||
set_module_type(drwtsn32 win32gui)
|
set_module_type(drwtsn32 win32gui UNICODE)
|
||||||
add_importlibs(drwtsn32 dbghelp psapi advapi32 shell32 msvcrt user32 kernel32 ntdll)
|
target_link_libraries(drwtsn32 atlnew)
|
||||||
|
add_importlibs(drwtsn32 dbghelp psapi advapi32 shell32 shlwapi msvcrt user32 kernel32 ntdll)
|
||||||
add_cd_file(TARGET drwtsn32 DESTINATION reactos/system32 FOR all)
|
add_cd_file(TARGET drwtsn32 DESTINATION reactos/system32 FOR all)
|
||||||
|
|
|
@ -59,18 +59,18 @@ bool UpdateFromEvent(DEBUG_EVENT& evt, DumpData& data)
|
||||||
{
|
{
|
||||||
case CREATE_PROCESS_DEBUG_EVENT:
|
case CREATE_PROCESS_DEBUG_EVENT:
|
||||||
{
|
{
|
||||||
data.ProcessPath.resize(MAX_PATH);
|
data.ProcessPath.resize(MAX_PATH*2);
|
||||||
DWORD len = GetModuleFileNameExA(evt.u.CreateProcessInfo.hProcess, NULL, &data.ProcessPath[0], data.ProcessPath.size());
|
DWORD len = GetModuleFileNameExW(evt.u.CreateProcessInfo.hProcess, NULL, &data.ProcessPath[0], data.ProcessPath.size());
|
||||||
if (len)
|
if (len)
|
||||||
{
|
{
|
||||||
data.ProcessPath.resize(len);
|
data.ProcessPath.resize(len);
|
||||||
std::string::size_type pos = data.ProcessPath.find_last_of("\\/");
|
std::string::size_type pos = data.ProcessPath.find_last_of(L"\\/");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
data.ProcessName = data.ProcessPath.substr(pos+1);
|
data.ProcessName = data.ProcessPath.substr(pos+1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data.ProcessPath = "??";
|
data.ProcessPath = L"??";
|
||||||
}
|
}
|
||||||
if (data.ProcessName.empty())
|
if (data.ProcessName.empty())
|
||||||
data.ProcessName = data.ProcessPath;
|
data.ProcessName = data.ProcessPath;
|
||||||
|
|
|
@ -36,8 +36,8 @@ typedef std::map<DWORD, ThreadData> ThreadMap;
|
||||||
class DumpData
|
class DumpData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string ProcessPath;
|
std::wstring ProcessPath;
|
||||||
std::string ProcessName;
|
std::wstring ProcessName;
|
||||||
DWORD ProcessID;
|
DWORD ProcessID;
|
||||||
DWORD ThreadID;
|
DWORD ThreadID;
|
||||||
HANDLE ProcessHandle;
|
HANDLE ProcessHandle;
|
||||||
|
|
21
base/applications/drwtsn32/drwtsn32.rc
Normal file
21
base/applications/drwtsn32/drwtsn32.rc
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: Dr. Watson crash reporter
|
||||||
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
||||||
|
* PURPOSE: Main resource file
|
||||||
|
* COPYRIGHT: Copyright 2018 William Kent (wjk011 [at] gmail [dot] com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windef.h>
|
||||||
|
#include <winuser.h>
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Crash Reporter"
|
||||||
|
#define REACTOS_STR_INTERNAL_NAME "drwtsn32"
|
||||||
|
#define REACTOS_STR_ORIGINAL_FILENAME "drwtsn32.exe"
|
||||||
|
#include <reactos/version.rc>
|
||||||
|
|
||||||
|
#include <reactos/manifest_exe.rc>
|
||||||
|
|
||||||
|
#ifdef LANGUAGE_EN_US
|
||||||
|
#include "lang/en-US.rc"
|
||||||
|
#endif
|
12
base/applications/drwtsn32/lang/en-US.rc
Normal file
12
base/applications/drwtsn32/lang/en-US.rc
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: Dr. Watson crash reporter
|
||||||
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
||||||
|
* PURPOSE: en-US resource file
|
||||||
|
* COPYRIGHT: Copyright 2018 William Kent (wjk011 [at] gmail [dot] com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_APP_TITLE "ReactOS Crash Reporter"
|
||||||
|
IDS_USER_ALERT_MESSAGE "The application %ls has crashed. Information about this crash has been saved to:\r\n\r\n%ls"
|
||||||
|
END
|
|
@ -9,9 +9,15 @@
|
||||||
#include <winuser.h>
|
#include <winuser.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#include <tchar.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
|
#include <dbghelp.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
#include <atlbase.h>
|
||||||
|
#include <atlstr.h>
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
|
||||||
static const char szUsage[] = "Usage: DrWtsn32 [-i] [-g] [-p dddd] [-e dddd] [-?]\n"
|
static const char szUsage[] = "Usage: DrWtsn32 [-i] [-g] [-p dddd] [-e dddd] [-?]\n"
|
||||||
|
@ -56,7 +62,7 @@ void PrintBugreport(FILE* output, DumpData& data)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
xfprintf(output, "%5d: %s" NEWLINE, pe.th32ProcessID, pe.szExeFile);
|
xfprintf(output, "%5d: %ls" NEWLINE, pe.th32ProcessID, pe.szExeFile);
|
||||||
} while (Process32Next(hSnap, &pe));
|
} while (Process32Next(hSnap, &pe));
|
||||||
}
|
}
|
||||||
CloseHandle(hSnap);
|
CloseHandle(hSnap);
|
||||||
|
@ -67,7 +73,7 @@ void PrintBugreport(FILE* output, DumpData& data)
|
||||||
|
|
||||||
ModuleData mainModule(NULL);
|
ModuleData mainModule(NULL);
|
||||||
mainModule.Update(data.ProcessHandle);
|
mainModule.Update(data.ProcessHandle);
|
||||||
xfprintf(output, "(%p - %p) %s" NEWLINE,
|
xfprintf(output, "(%p - %p) %ls" NEWLINE,
|
||||||
mainModule.BaseAddress,
|
mainModule.BaseAddress,
|
||||||
(PBYTE)mainModule.BaseAddress + mainModule.Size,
|
(PBYTE)mainModule.BaseAddress + mainModule.Size,
|
||||||
data.ProcessPath.c_str());
|
data.ProcessPath.c_str());
|
||||||
|
@ -144,11 +150,41 @@ int abort(FILE* output, int err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
std::wstring Settings_GetOutputPath(void)
|
||||||
{
|
{
|
||||||
|
WCHAR Buffer[MAX_PATH] = L"";
|
||||||
|
ULONG BufferSize = _countof(Buffer);
|
||||||
|
BOOL UseDefaultPath = FALSE;
|
||||||
|
|
||||||
|
CRegKey key;
|
||||||
|
if (key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\ReactOS\\Crash Reporter", KEY_READ) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
UseDefaultPath = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.QueryStringValue(L"Dump Directory", Buffer, &BufferSize) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
UseDefaultPath = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UseDefaultPath)
|
||||||
|
{
|
||||||
|
if (FAILED(SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, Buffer)))
|
||||||
|
{
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::wstring(Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR cmdLine, INT)
|
||||||
|
{
|
||||||
|
int argc;
|
||||||
|
WCHAR **argv = CommandLineToArgvW(cmdLine, &argc);
|
||||||
|
|
||||||
DWORD pid = 0;
|
DWORD pid = 0;
|
||||||
char Buffer[MAX_PATH+55];
|
WCHAR Filename[50];
|
||||||
char Filename[50];
|
|
||||||
FILE* output = NULL;
|
FILE* output = NULL;
|
||||||
SYSTEMTIME st;
|
SYSTEMTIME st;
|
||||||
DumpData data;
|
DumpData data;
|
||||||
|
@ -156,37 +192,37 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
for (int n = 0; n < argc; ++n)
|
for (int n = 0; n < argc; ++n)
|
||||||
{
|
{
|
||||||
char* arg = argv[n];
|
WCHAR* arg = argv[n];
|
||||||
|
|
||||||
if (!strcmp(arg, "-i"))
|
if (!wcscmp(arg, L"-i"))
|
||||||
{
|
{
|
||||||
/* FIXME: Installs as the postmortem debugger. */
|
/* FIXME: Installs as the postmortem debugger. */
|
||||||
}
|
}
|
||||||
else if (!strcmp(arg, "-g"))
|
else if (!wcscmp(arg, L"-g"))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
else if (!strcmp(arg, "-p"))
|
else if (!wcscmp(arg, L"-p"))
|
||||||
{
|
{
|
||||||
if (n + 1 < argc)
|
if (n + 1 < argc)
|
||||||
{
|
{
|
||||||
pid = strtoul(argv[n+1], NULL, 10);
|
pid = wcstoul(argv[n+1], NULL, 10);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(arg, "-e"))
|
else if (!wcscmp(arg, L"-e"))
|
||||||
{
|
{
|
||||||
if (n + 1 < argc)
|
if (n + 1 < argc)
|
||||||
{
|
{
|
||||||
data.Event = (HANDLE)strtoul(argv[n+1], NULL, 10);
|
data.Event = (HANDLE)wcstoul(argv[n+1], NULL, 10);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(arg, "-?"))
|
else if (!wcscmp(arg, L"-?"))
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, szUsage, "DrWtsn32", MB_OK);
|
MessageBoxA(NULL, szUsage, "ReactOS Crash Reporter", MB_OK);
|
||||||
return abort(output, 0);
|
return abort(output, 0);
|
||||||
}
|
}
|
||||||
else if (!strcmp(arg, "/?"))
|
else if (!wcscmp(arg, L"/?"))
|
||||||
{
|
{
|
||||||
xfprintf(stdout, "%s\n", szUsage);
|
xfprintf(stdout, "%s\n", szUsage);
|
||||||
return abort(stdout, 0);
|
return abort(stdout, 0);
|
||||||
|
@ -195,19 +231,33 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
if (!pid)
|
if (!pid)
|
||||||
{
|
{
|
||||||
MessageBoxA(NULL, szUsage, "DrWtsn32", MB_OK);
|
MessageBoxA(NULL, szUsage, "ReactOS Crash Reporter", MB_OK);
|
||||||
return abort(stdout, 0);
|
return abort(stdout, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetLocalTime(&st);
|
GetLocalTime(&st);
|
||||||
|
|
||||||
if (SHGetFolderPathA(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, Buffer) == S_OK &&
|
std::wstring OutputPath = Settings_GetOutputPath();
|
||||||
SUCCEEDED(StringCchPrintfA(Filename, _countof(Filename), "Appcrash_%d-%02d-%02d_%02d-%02d-%02d.txt",
|
BOOL HasPath = (OutputPath.size() != 0);
|
||||||
|
|
||||||
|
if (!PathIsDirectoryW(OutputPath.c_str()))
|
||||||
|
{
|
||||||
|
int res = SHCreateDirectoryExW(NULL, OutputPath.c_str(), NULL);
|
||||||
|
if (res != ERROR_SUCCESS && res != ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
xfprintf(stdout, "Could not create output directory, not writing dump\n");
|
||||||
|
MessageBoxA(NULL, "Could not create directory to write crash report.", "ReactOS Crash Reporter", MB_ICONERROR | MB_OK);
|
||||||
|
return abort(stdout, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasPath &&
|
||||||
|
SUCCEEDED(StringCchPrintfW(Filename, _countof(Filename), L"Appcrash_%d-%02d-%02d_%02d-%02d-%02d.txt",
|
||||||
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond)))
|
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond)))
|
||||||
{
|
{
|
||||||
StringCchCatA(Buffer, _countof(Buffer), "\\");
|
OutputPath += L"\\";
|
||||||
StringCchCatA(Buffer, _countof(Buffer), Filename);
|
OutputPath += Filename;
|
||||||
output = fopen(Buffer, "wb");
|
output = _wfopen(OutputPath.c_str(), L"wb");
|
||||||
}
|
}
|
||||||
if (!output)
|
if (!output)
|
||||||
output = stdout;
|
output = stdout;
|
||||||
|
@ -237,13 +287,12 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
TerminateProcess(data.ProcessHandle, data.ExceptionInfo.ExceptionRecord.ExceptionCode);
|
TerminateProcess(data.ProcessHandle, data.ExceptionInfo.ExceptionRecord.ExceptionCode);
|
||||||
|
|
||||||
std::string Message = "The application '";
|
CStringW FormattedMessage;
|
||||||
Message += data.ProcessName;
|
FormattedMessage.Format(IDS_USER_ALERT_MESSAGE, data.ProcessName.c_str(), OutputPath.c_str());
|
||||||
Message += "' has just crashed :(\n";
|
CStringW DialogTitle;
|
||||||
Message += "Information about this crash is saved to:\n";
|
DialogTitle.LoadString(hInstance, IDS_APP_TITLE);
|
||||||
Message += Filename;
|
|
||||||
Message += "\nThis file is stored on your desktop.";
|
MessageBoxW(NULL, FormattedMessage.GetString(), DialogTitle.GetString(), MB_OK);
|
||||||
MessageBoxA(NULL, Message.c_str(), "Sorry!", MB_OK);
|
|
||||||
|
|
||||||
return abort(output, 0);
|
return abort(output, 0);
|
||||||
}
|
}
|
||||||
|
|
11
base/applications/drwtsn32/resource.h
Normal file
11
base/applications/drwtsn32/resource.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: Dr. Watson crash reporter
|
||||||
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
||||||
|
* PURPOSE: Resource file header
|
||||||
|
* COPYRIGHT: Copyright 2018 William Kent (wjk011 [at] gmail [dot] com)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define IDS_APP_TITLE 101
|
||||||
|
#define IDS_USER_ALERT_MESSAGE 102
|
|
@ -54,7 +54,7 @@ void PrintSystemInfo(FILE* output, DumpData& data)
|
||||||
GetLocalTime(&LocalTime);
|
GetLocalTime(&LocalTime);
|
||||||
xfprintf(output, NEWLINE "ReactOS " KERNEL_VERSION_STR " DrWtsn32" NEWLINE NEWLINE);
|
xfprintf(output, NEWLINE "ReactOS " KERNEL_VERSION_STR " DrWtsn32" NEWLINE NEWLINE);
|
||||||
xfprintf(output, "Application exception occurred:" NEWLINE);
|
xfprintf(output, "Application exception occurred:" NEWLINE);
|
||||||
xfprintf(output, " App: %s (pid=%d, tid=0x%x)" NEWLINE, data.ProcessName.c_str(), data.ProcessID, data.ThreadID);
|
xfprintf(output, " App: %ls (pid=%d, tid=0x%x)" NEWLINE, data.ProcessName.c_str(), data.ProcessID, data.ThreadID);
|
||||||
xfprintf(output, " When: %d/%d/%d @ %02d:%02d:%02d.%d" NEWLINE,
|
xfprintf(output, " When: %d/%d/%d @ %02d:%02d:%02d.%d" NEWLINE,
|
||||||
LocalTime.wDay, LocalTime.wMonth, LocalTime.wYear,
|
LocalTime.wDay, LocalTime.wMonth, LocalTime.wYear,
|
||||||
LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond, LocalTime.wMilliseconds);
|
LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond, LocalTime.wMilliseconds);
|
||||||
|
|
Loading…
Reference in a new issue