diff --git a/DalamudCrashHandler/DalamudCrashHandler.cpp b/DalamudCrashHandler/DalamudCrashHandler.cpp
index 09e14d722..74e770ec0 100644
--- a/DalamudCrashHandler/DalamudCrashHandler.cpp
+++ b/DalamudCrashHandler/DalamudCrashHandler.cpp
@@ -610,6 +610,7 @@ enum {
IdRadioRestartWithoutDalamud,
IdButtonRestart = 201,
+ IdButtonSaveTsPack = 202,
IdButtonHelp = IDHELP,
IdButtonExit = IDCANCEL,
};
@@ -758,9 +759,9 @@ int main() {
std::cout << "Creating progress window" << std::endl;
IProgressDialog* pProgressDialog = NULL;
if (SUCCEEDED(CoCreateInstance(CLSID_ProgressDialog, NULL, CLSCTX_ALL, IID_IProgressDialog, (void**)&pProgressDialog)) && pProgressDialog) {
- pProgressDialog->SetTitle(L"Dalamud");
- pProgressDialog->SetLine(1, L"The game has crashed", FALSE, NULL);
- pProgressDialog->SetLine(2, L"Dalamud is collecting further information", FALSE, NULL);
+ pProgressDialog->SetTitle(L"Dalamud Crash Handler");
+ pProgressDialog->SetLine(1, L"The game has crashed!", FALSE, NULL);
+ pProgressDialog->SetLine(2, L"Dalamud is collecting further information...", FALSE, NULL);
pProgressDialog->SetLine(3, L"Refreshing Game Module List", FALSE, NULL);
pProgressDialog->StartProgressDialog(NULL, NULL, PROGDLG_MARQUEEPROGRESS | PROGDLG_NOCANCEL | PROGDLG_NOMINIMIZE, NULL);
IOleWindow* pOleWindow;
@@ -904,64 +905,24 @@ int main() {
print_exception_info_extended(exinfo.ExceptionPointers, exinfo.ContextRecord, log);
std::wofstream(logPath) << log.str();
- std::thread submitThread;
- if (!getenv("DALAMUD_NO_METRIC")) {
- auto url = std::format(L"/Dalamud/Metric/ReportCrash?lt={}&code={:x}", exinfo.nLifetime, exinfo.ExceptionRecord.ExceptionCode);
-
- submitThread = std::thread([url = std::move(url)] {
- const auto hInternet = WinHttpOpen(L"Dalamud Crash Handler/1.0",
- WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
- WINHTTP_NO_PROXY_NAME,
- WINHTTP_NO_PROXY_BYPASS, 0);
- const auto hConnect = !hInternet ? nullptr : WinHttpConnect(hInternet, L"kamori.goats.dev", INTERNET_DEFAULT_HTTP_PORT, 0);
- const auto hRequest = !hConnect ? nullptr : WinHttpOpenRequest(hConnect, L"GET", url.c_str(), NULL, WINHTTP_NO_REFERER,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- 0);
- if (hRequest) WinHttpAddRequestHeaders(hRequest, L"Host: kamori.goats.dev", (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD);
- const auto bSent = !hRequest ? false : WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS,
- 0, WINHTTP_NO_REQUEST_DATA, 0,
- 0, 0);
-
- if (!bSent)
- std::cerr << std::format("Failed to send metric: 0x{:x}", GetLastError()) << std::endl;
-
- if (WinHttpReceiveResponse(hRequest, nullptr))
- {
- DWORD dwStatusCode = 0;
- DWORD dwStatusCodeSize = sizeof(DWORD);
-
- WinHttpQueryHeaders(hRequest,
- WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
- WINHTTP_HEADER_NAME_BY_INDEX,
- &dwStatusCode, &dwStatusCodeSize, WINHTTP_NO_HEADER_INDEX);
-
- if (dwStatusCode != 200)
- std::cerr << std::format("Failed to send metric: {}", dwStatusCode) << std::endl;
- }
-
- if (hRequest) WinHttpCloseHandle(hRequest);
- if (hConnect) WinHttpCloseHandle(hConnect);
- if (hInternet) WinHttpCloseHandle(hInternet);
- });
- }
-
TASKDIALOGCONFIG config = { 0 };
const TASKDIALOG_BUTTON radios[]{
- {IdRadioRestartNormal, L"Restart"},
- {IdRadioRestartWithout3pPlugins, L"Restart without 3rd party plugins"},
+ {IdRadioRestartNormal, L"Restart normally"},
+ {IdRadioRestartWithout3pPlugins, L"Restart without custom repository plugins"},
{IdRadioRestartWithoutPlugins, L"Restart without any plugins"},
{IdRadioRestartWithoutDalamud, L"Restart without Dalamud"},
};
const TASKDIALOG_BUTTON buttons[]{
- {IdButtonRestart, L"Restart\nRestart the game, optionally without plugins or Dalamud."},
+ {IdButtonRestart, L"Restart\nRestart the game with the above-selected option."},
+ {IdButtonSaveTsPack, L"Save Troubleshooting Info\nSave a .tspack file containing information about this crash for analysis."},
{IdButtonExit, L"Exit\nExit the game."},
};
config.cbSize = sizeof(config);
config.hInstance = GetModuleHandleW(nullptr);
- config.dwFlags = TDF_ENABLE_HYPERLINKS | TDF_CAN_BE_MINIMIZED | TDF_ALLOW_DIALOG_CANCELLATION | TDF_USE_COMMAND_LINKS;
+ config.dwFlags = TDF_ENABLE_HYPERLINKS | TDF_CAN_BE_MINIMIZED | TDF_ALLOW_DIALOG_CANCELLATION | TDF_USE_COMMAND_LINKS | TDF_NO_DEFAULT_RADIO_BUTTON;
config.pszMainIcon = MAKEINTRESOURCE(IDI_ICON1);
config.pszMainInstruction = L"An error in the game occurred";
config.pszContent = (L""
@@ -969,7 +930,7 @@ int main() {
"\n"
R"aa(Try running a game repair in XIVLauncher by right clicking the login button, and disabling plugins you don't need. Please also check your antivirus, see our help site for more information.)aa" "\n"
"\n"
- R"aa(Upload this file (click here) if you want to ask for help in our Discord server.)aa" "\n"
+ R"aa(For further assistance, please upload a troubleshooting pack to our Discord server.)aa" "\n"
);
config.pButtons = buttons;
@@ -978,10 +939,9 @@ int main() {
config.pszExpandedControlText = L"Hide stack trace";
config.pszCollapsedControlText = L"Stack trace for plugin developers";
config.pszExpandedInformation = window_log_str.c_str();
- config.pszWindowTitle = L"Dalamud Error";
+ config.pszWindowTitle = L"Dalamud Crash Handler";
config.pRadioButtons = radios;
config.cRadioButtons = ARRAYSIZE(radios);
- config.nDefaultRadioButton = IdRadioRestartNormal;
config.cxWidth = 300;
#if _DEBUG
@@ -1003,6 +963,7 @@ int main() {
case TDN_CREATED:
{
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+ SendMessage(hwnd, TDM_ENABLE_BUTTON, IdButtonRestart, 0);
return S_OK;
}
case TDN_HYPERLINK_CLICKED:
@@ -1024,6 +985,18 @@ int main() {
}
return S_OK;
}
+ case TDN_RADIO_BUTTON_CLICKED:
+ SendMessage(hwnd, TDM_ENABLE_BUTTON, IdButtonRestart, 1);
+ return S_OK;
+ case TDN_BUTTON_CLICKED:
+ const auto button = static_cast(wParam);
+ if (button == IdButtonSaveTsPack)
+ {
+ export_tspack(hwnd, logDir, ws_to_u8(log.str()), troubleshootingPackData);
+ return S_FALSE; // keep the dialog open
+ }
+
+ return S_OK;
}
return S_OK;
@@ -1033,15 +1006,7 @@ int main() {
return (*reinterpret_cast(dwRefData))(hwnd, uNotification, wParam, lParam);
};
config.lpCallbackData = reinterpret_cast(&callback);
-
- if (pProgressDialog)
- pProgressDialog->SetLine(3, L"Submitting Metrics", FALSE, NULL);
-
- if (submitThread.joinable()) {
- submitThread.join();
- submitThread = {};
- }
-
+
if (pProgressDialog) {
pProgressDialog->StopProgressDialog();
pProgressDialog->Release();