[DRWTSN32] Various improvements
authorWilliam Kent <wjk011@gmail.com>
Thu, 8 Mar 2018 19:50:29 +0000 (20:50 +0100)
committerMark Jansen <mark.jansen@reactos.org>
Fri, 9 Mar 2018 23:04:57 +0000 (00:04 +0100)
* 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

base/applications/drwtsn32/CMakeLists.txt
base/applications/drwtsn32/drwtsn32.cpp
base/applications/drwtsn32/drwtsn32.h
base/applications/drwtsn32/drwtsn32.rc [new file with mode: 0644]
base/applications/drwtsn32/lang/en-US.rc [new file with mode: 0644]
base/applications/drwtsn32/main.cpp
base/applications/drwtsn32/resource.h [new file with mode: 0644]
base/applications/drwtsn32/sysinfo.cpp

index 3a7e93f..66dbdab 100644 (file)
@@ -2,6 +2,7 @@
 PROJECT(drwtsn32)
 
 set_cpp(WITH_RUNTIME WITH_EXCEPTIONS WITH_STL)
+include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/atl)
 
 list(APPEND CPP_SOURCE
     drwtsn32.cpp
@@ -11,8 +12,9 @@ list(APPEND CPP_SOURCE
     drwtsn32.h
     precomp.h)
 
-add_executable(drwtsn32 ${CPP_SOURCE})
+add_executable(drwtsn32 ${CPP_SOURCE} drwtsn32.rc)
 add_pch(drwtsn32 precomp.h CPP_SOURCE)
-set_module_type(drwtsn32 win32gui)
-add_importlibs(drwtsn32 dbghelp psapi advapi32 shell32 msvcrt user32 kernel32 ntdll)
+set_module_type(drwtsn32 win32gui UNICODE)
+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)
index b667dd7..598e4f0 100644 (file)
@@ -59,18 +59,18 @@ bool UpdateFromEvent(DEBUG_EVENT& evt, DumpData& data)
     {
     case CREATE_PROCESS_DEBUG_EVENT:
     {
-        data.ProcessPath.resize(MAX_PATH);
-        DWORD len = GetModuleFileNameExA(evt.u.CreateProcessInfo.hProcess, NULL, &data.ProcessPath[0], data.ProcessPath.size());
+        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("\\/");
+            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 = "??";
+            data.ProcessPath = L"??";
         }
         if (data.ProcessName.empty())
             data.ProcessName = data.ProcessPath;
index 4d161ff..a16b2f3 100644 (file)
@@ -36,8 +36,8 @@ typedef std::map<DWORD, ThreadData> ThreadMap;
 class DumpData
 {
 public:
-    std::string ProcessPath;
-    std::string ProcessName;
+    std::wstring ProcessPath;
+    std::wstring ProcessName;
     DWORD ProcessID;
     DWORD ThreadID;
     HANDLE ProcessHandle;
diff --git a/base/applications/drwtsn32/drwtsn32.rc b/base/applications/drwtsn32/drwtsn32.rc
new file mode 100644 (file)
index 0000000..0f3e210
--- /dev/null
@@ -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
diff --git a/base/applications/drwtsn32/lang/en-US.rc b/base/applications/drwtsn32/lang/en-US.rc
new file mode 100644 (file)
index 0000000..d681297
--- /dev/null
@@ -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
index 65c7dc1..1224b75 100644 (file)
@@ -9,9 +9,15 @@
 #include <winuser.h>
 #include <algorithm>
 #include <shlobj.h>
+#include <shlwapi.h>
+#include <tchar.h>
 #include <strsafe.h>
 #include <tlhelp32.h>
+#include <dbghelp.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"
@@ -56,7 +62,7 @@ void PrintBugreport(FILE* output, DumpData& data)
         {
             do
             {
-                xfprintf(output, "%5d: %s" NEWLINE, pe.th32ProcessID, pe.szExeFile);
+                xfprintf(output, "%5d: %ls" NEWLINE, pe.th32ProcessID, pe.szExeFile);
             } while (Process32Next(hSnap, &pe));
         }
         CloseHandle(hSnap);
@@ -67,7 +73,7 @@ void PrintBugreport(FILE* output, DumpData& data)
 
     ModuleData mainModule(NULL);
     mainModule.Update(data.ProcessHandle);
-    xfprintf(output, "(%p - %p) %s" NEWLINE,
+    xfprintf(output, "(%p - %p) %ls" NEWLINE,
              mainModule.BaseAddress,
              (PBYTE)mainModule.BaseAddress + mainModule.Size,
              data.ProcessPath.c_str());
@@ -144,11 +150,41 @@ int abort(FILE* output, int 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;
-    char Buffer[MAX_PATH+55];
-    char Filename[50];
+    WCHAR Filename[50];
     FILE* output = NULL;
     SYSTEMTIME st;
     DumpData data;
@@ -156,37 +192,37 @@ int main(int argc, char* argv[])
 
     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. */
         }
-        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)
             {
-                pid = strtoul(argv[n+1], NULL, 10);
+                pid = wcstoul(argv[n+1], NULL, 10);
                 n++;
             }
         }
-        else if (!strcmp(arg, "-e"))
+        else if (!wcscmp(arg, L"-e"))
         {
             if (n + 1 < argc)
             {
-                data.Event = (HANDLE)strtoul(argv[n+1], NULL, 10);
+                data.Event = (HANDLE)wcstoul(argv[n+1], NULL, 10);
                 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);
         }
-        else if (!strcmp(arg, "/?"))
+        else if (!wcscmp(arg, L"/?"))
         {
             xfprintf(stdout, "%s\n", szUsage);
             return abort(stdout, 0);
@@ -195,19 +231,33 @@ int main(int argc, char* argv[])
 
     if (!pid)
     {
-        MessageBoxA(NULL, szUsage, "DrWtsn32", MB_OK);
+        MessageBoxA(NULL, szUsage, "ReactOS Crash Reporter", MB_OK);
         return abort(stdout, 0);
     }
 
     GetLocalTime(&st);
 
-    if (SHGetFolderPathA(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, Buffer) == S_OK &&
-        SUCCEEDED(StringCchPrintfA(Filename, _countof(Filename), "Appcrash_%d-%02d-%02d_%02d-%02d-%02d.txt",
+    std::wstring OutputPath = Settings_GetOutputPath();
+    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)))
     {
-        StringCchCatA(Buffer, _countof(Buffer), "\\");
-        StringCchCatA(Buffer, _countof(Buffer), Filename);
-        output = fopen(Buffer, "wb");
+        OutputPath += L"\\";
+        OutputPath += Filename;
+        output = _wfopen(OutputPath.c_str(), L"wb");
     }
     if (!output)
         output = stdout;
@@ -237,13 +287,12 @@ int main(int argc, char* argv[])
 
     TerminateProcess(data.ProcessHandle, data.ExceptionInfo.ExceptionRecord.ExceptionCode);
 
-    std::string Message = "The application '";
-    Message += data.ProcessName;
-    Message += "' has just crashed :(\n";
-    Message += "Information about this crash is saved to:\n";
-    Message += Filename;
-    Message += "\nThis file is stored on your desktop.";
-    MessageBoxA(NULL, Message.c_str(), "Sorry!", MB_OK);
+    CStringW FormattedMessage;
+    FormattedMessage.Format(IDS_USER_ALERT_MESSAGE, data.ProcessName.c_str(), OutputPath.c_str());
+    CStringW DialogTitle;
+    DialogTitle.LoadString(hInstance, IDS_APP_TITLE);
+
+    MessageBoxW(NULL, FormattedMessage.GetString(), DialogTitle.GetString(), MB_OK);
 
     return abort(output, 0);
 }
diff --git a/base/applications/drwtsn32/resource.h b/base/applications/drwtsn32/resource.h
new file mode 100644 (file)
index 0000000..064207e
--- /dev/null
@@ -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
index 7cad0ca..7148163 100644 (file)
@@ -54,7 +54,7 @@ void PrintSystemInfo(FILE* output, DumpData& data)
     GetLocalTime(&LocalTime);
     xfprintf(output, NEWLINE "ReactOS " KERNEL_VERSION_STR " DrWtsn32" NEWLINE 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,
              LocalTime.wDay, LocalTime.wMonth, LocalTime.wYear,
              LocalTime.wHour, LocalTime.wMinute, LocalTime.wSecond, LocalTime.wMilliseconds);