/** * Default directory fallback is: * - (command line argument) * - <platform dependent> */ void platform_resolve_user_data_path() { const char separator[2] = { platform_get_path_separator(), 0 }; if (gCustomUserDataPath[0] != 0) { if (realpath(gCustomUserDataPath, _userDataDirectoryPath) == NULL) { log_error("Could not resolve path \"%s\"", gCustomUserDataPath); return; } // Ensure path ends with separator int len = strlen(_userDataDirectoryPath); if (_userDataDirectoryPath[len - 1] != separator[0]) { strncat(_userDataDirectoryPath, separator, MAX_PATH - 1); } return; } char buffer[MAX_PATH]; buffer[0] = '\0'; log_verbose("buffer = '%s'", buffer); const char *homedir = getpwuid(getuid())->pw_dir; platform_posix_sub_user_data_path(buffer, homedir, separator); log_verbose("OpenRCT2 user data directory = '%s'", buffer); int len = strnlen(buffer, MAX_PATH); wchar_t *w_buffer = regular_to_wchar(buffer); w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); safe_strcpy(_userDataDirectoryPath, path, MAX_PATH); free(path); }
/** * Default directory fallback is: * - (command line argument) * - $XDG_CONFIG_HOME/.config/OpenRCT2 * - /home/[uid]/.config/OpenRCT2 */ void platform_resolve_user_data_path() { const char separator[2] = { platform_get_path_separator(), 0 }; if (gCustomUserDataPath[0] != 0) { realpath(gCustomUserDataPath, _userDataDirectoryPath); // Ensure path ends with separator int len = strlen(_userDataDirectoryPath); if (_userDataDirectoryPath[len - 1] != separator[0]) { strcat(_userDataDirectoryPath, separator); } return; } char buffer[MAX_PATH]; buffer[0] = '\0'; log_verbose("buffer = '%s'", buffer); const char *homedir = getenv("XDG_CONFIG_HOME"); log_verbose("homedir = '%s'", homedir); if (homedir == NULL) { homedir = getpwuid(getuid())->pw_dir; log_verbose("homedir was null, used getuid, now is = '%s'", homedir); if (homedir == NULL) { log_fatal("Couldn't find user data directory"); exit(-1); return; } strncat(buffer, homedir, MAX_PATH); strncat(buffer, separator, MAX_PATH); strncat(buffer, ".config", MAX_PATH); } else { strncat(buffer, homedir, MAX_PATH); } strncat(buffer, separator, MAX_PATH); strncat(buffer, "OpenRCT2", MAX_PATH); strncat(buffer, separator, MAX_PATH); log_verbose("OpenRCT2 user data directory = '%s'", buffer); int len = strnlen(buffer, MAX_PATH); wchar_t *w_buffer = regular_to_wchar(buffer); w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); safe_strncpy(_userDataDirectoryPath, path, MAX_PATH); free(path); }
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory, size_t outSize) { char buffer[MAX_PATH]; safe_strcpy(buffer, _userDataDirectoryPath, sizeof(buffer)); if (subDirectory != NULL && subDirectory[0] != 0) { log_verbose("adding subDirectory '%s'", subDirectory); safe_strcat_path(buffer, subDirectory, sizeof(buffer)); path_end_with_separator(buffer, sizeof(buffer)); } sint32 len = strnlen(buffer, MAX_PATH); wchar_t *w_buffer = regular_to_wchar(buffer); w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); safe_strcpy(outPath, path, outSize); free(path); log_verbose("outPath + subDirectory = '%s'", buffer); }
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory) { const char separator[2] = { platform_get_path_separator(), 0 }; char buffer[MAX_PATH]; safe_strcpy(buffer, _userDataDirectoryPath, sizeof(buffer)); if (subDirectory != NULL && subDirectory[0] != 0) { log_verbose("adding subDirectory '%s'", subDirectory); strncat(buffer, subDirectory, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); } int len = strnlen(buffer, MAX_PATH); wchar_t *w_buffer = regular_to_wchar(buffer); w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); safe_strcpy(outPath, path, MAX_PATH); free(path); log_verbose("outPath + subDirectory = '%s'", buffer); }
/** * Default directory fallback is: * - (command line argument) * - <platform dependent> */ void platform_resolve_user_data_path() { if (gCustomUserDataPath[0] != 0) { if (!platform_ensure_directory_exists(gCustomUserDataPath)) { log_error("Failed to create directory \"%s\", make sure you have permissions.", gCustomUserDataPath); return; } char *path; if ((path = realpath(gCustomUserDataPath, NULL)) == NULL) { log_error("Could not resolve path \"%s\"", gCustomUserDataPath); return; } safe_strcpy(_userDataDirectoryPath, path, MAX_PATH); free(path); // Ensure path ends with separator path_end_with_separator(_userDataDirectoryPath, MAX_PATH); log_verbose("User data path resolved to: %s", _userDataDirectoryPath); if (!platform_directory_exists(_userDataDirectoryPath)) { log_error("Custom user data directory %s does not exist", _userDataDirectoryPath); } return; } char buffer[MAX_PATH]; log_verbose("buffer = '%s'", buffer); const char *homedir = getpwuid(getuid())->pw_dir; platform_posix_sub_user_data_path(buffer, MAX_PATH, homedir); log_verbose("OpenRCT2 user data directory = '%s'", buffer); sint32 len = strnlen(buffer, MAX_PATH); wchar_t *w_buffer = regular_to_wchar(buffer); w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); safe_strcpy(_userDataDirectoryPath, path, MAX_PATH); free(path); log_verbose("User data path resolved to: %s", _userDataDirectoryPath); }
static bool OnCrash(const wchar_t * dumpPath, const wchar_t * miniDumpId, void * context, EXCEPTION_POINTERS * exinfo, MDRawAssertionInfo * assertion, bool succeeded) { if (!succeeded) { constexpr const char * DumpFailedMessage = "Failed to create the dump. Please file an issue with OpenRCT2 on GitHub and provide latest save, and provide information about what you did before the crash occured."; printf("%s\n", DumpFailedMessage); if (!gOpenRCT2SilentBreakpad) { MessageBoxA(NULL, DumpFailedMessage, OPENRCT2_NAME, MB_OK | MB_ICONERROR); } return succeeded; } // Get filenames wchar_t dumpFilePath[MAX_PATH]; wchar_t saveFilePath[MAX_PATH]; swprintf_s(dumpFilePath, sizeof(dumpFilePath), L"%s%s.dmp", dumpPath, miniDumpId); swprintf_s(saveFilePath, sizeof(saveFilePath), L"%s%s.sv6", dumpPath, miniDumpId); // Try to rename the files wchar_t dumpFilePathNew[MAX_PATH]; swprintf_s(dumpFilePathNew, sizeof(dumpFilePathNew), L"%s%s(%s_%s).dmp", dumpPath, miniDumpId, _wszCommitSha1Short, _wszArchitecture); if (_wrename(dumpFilePath, dumpFilePathNew) == 0) { std::wcscpy(dumpFilePath, dumpFilePathNew); } // Log information to output wprintf(L"Dump Path: %s\n", dumpPath); wprintf(L"Dump File Path: %s\n", dumpFilePath); wprintf(L"Dump Id: %s\n", miniDumpId); wprintf(L"Version: %s\n", WSZ(OPENRCT2_VERSION)); wprintf(L"Commit: %s\n", _wszCommitSha1Short); utf8 * saveFilePathUTF8 = widechar_to_utf8(saveFilePath); SDL_RWops * rw = SDL_RWFromFile(saveFilePathUTF8, "wb+"); free(saveFilePathUTF8); bool savedGameDumped = false; if (rw != NULL) { scenario_save(rw, 0x80000000); savedGameDumped = true; SDL_RWclose(rw); } if (gOpenRCT2SilentBreakpad) { return succeeded; } constexpr const wchar_t * MessageFormat = L"A crash has occurred and a dump was created at\n%s.\n\nPlease file an issue with OpenRCT2 on GitHub, and provide the dump and saved game there.\n\nVersion: %s\nCommit: %s"; wchar_t message[MAX_PATH * 2]; swprintf_s(message, MessageFormat, dumpFilePath, WSZ(OPENRCT2_VERSION), _wszCommitSha1Short); // Cannot use platform_show_messagebox here, it tries to set parent window already dead. MessageBoxW(NULL, message, WSZ(OPENRCT2_NAME), MB_OK | MB_ICONERROR); HRESULT coInitializeResult = CoInitialize(NULL); if (SUCCEEDED(coInitializeResult)) { LPITEMIDLIST pidl = ILCreateFromPathW(dumpPath); LPITEMIDLIST files[2]; uint32 numFiles = 0; files[numFiles++] = ILCreateFromPathW(dumpFilePath); if (savedGameDumped) { files[numFiles++] = ILCreateFromPathW(saveFilePath); } if (pidl != nullptr) { HRESULT result = SHOpenFolderAndSelectItems(pidl, numFiles, (LPCITEMIDLIST *)files, 0); ILFree(pidl); for (uint32 i = 0; i < numFiles; i++) { ILFree(files[i]); } } CoUninitialize(); } // Return whether the dump was successful return succeeded; }