diff --git a/src/openrct2/CmdlineSprite.cpp b/src/openrct2/CmdlineSprite.cpp index d3b4bf375b..ea4e9945e8 100644 --- a/src/openrct2/CmdlineSprite.cpp +++ b/src/openrct2/CmdlineSprite.cpp @@ -13,6 +13,7 @@ #include "OpenRCT2.h" #include "core/Imaging.h" +#include "core/String.hpp" #include "drawing/Drawing.h" #include "drawing/ImageImporter.h" #include "localisation/Language.h" @@ -68,11 +69,9 @@ static uint8_t* spriteFileData; static FILE* fopen_utf8(const char* path, const char* mode) { - wchar_t* pathW = utf8_to_widechar(path); - wchar_t* modeW = utf8_to_widechar(mode); - FILE* file = _wfopen(pathW, modeW); - free(pathW); - free(modeW); + auto pathW = String::ToUtf16(path); + auto modeW = String::ToUtf16(mode); + auto file = _wfopen(pathW.c_str(), modeW.c_str()); return file; } @@ -640,20 +639,19 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc) } // Resolve absolute sprite path - char* imagePath = platform_get_absolute_path(json_string_value(path), directoryPath); + auto imagePath = platform_get_absolute_path(json_string_value(path), directoryPath); rct_g1_element spriteElement; uint8_t* buffer; int bufferLength; if (!sprite_file_import( - imagePath, x_offset == nullptr ? 0 : json_integer_value(x_offset), + imagePath.c_str(), x_offset == nullptr ? 0 : json_integer_value(x_offset), y_offset == nullptr ? 0 : json_integer_value(y_offset), keep_palette, forceBmp, &spriteElement, &buffer, &bufferLength, gSpriteMode)) { - fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath); + fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath.c_str()); json_decref(sprite_list); - free(imagePath); return -1; } @@ -661,7 +659,6 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc) { fprintf(stderr, "Unable to open sprite file: %s\nCanceling\n", spriteFilePath); json_decref(sprite_list); - free(imagePath); return -1; } @@ -683,16 +680,14 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc) if (!sprite_file_save(spriteFilePath)) { - fprintf(stderr, "Could not save sprite file: %s\nCanceling\n", imagePath); + fprintf(stderr, "Could not save sprite file: %s\nCanceling\n", imagePath.c_str()); json_decref(sprite_list); - free(imagePath); return -1; } if (!silent) - fprintf(stdout, "Added: %s\n", imagePath); + fprintf(stdout, "Added: %s\n", imagePath.c_str()); - free(imagePath); sprite_file_close(); } diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index 556c461501..08d59488ee 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -362,7 +362,7 @@ namespace Config auto playerName = reader->GetString("player_name", ""); if (playerName.empty()) { - playerName = String::ToStd(platform_get_username()); + playerName = platform_get_username(); if (playerName.empty()) { playerName = "Player"; diff --git a/src/openrct2/core/File.cpp b/src/openrct2/core/File.cpp index bae6d23440..df3220daf7 100644 --- a/src/openrct2/core/File.cpp +++ b/src/openrct2/core/File.cpp @@ -125,8 +125,8 @@ namespace File { uint64_t lastModified = 0; #ifdef _WIN32 - auto pathW = utf8_to_widechar(path.c_str()); - auto hFile = CreateFileW(pathW, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); + auto pathW = String::ToUtf16(path.c_str()); + auto hFile = CreateFileW(pathW.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); if (hFile != INVALID_HANDLE_VALUE) { FILETIME ftCreate, ftAccess, ftWrite; @@ -136,7 +136,6 @@ namespace File } CloseHandle(hFile); } - free(pathW); #else struct stat statInfo { diff --git a/src/openrct2/core/FileScanner.cpp b/src/openrct2/core/FileScanner.cpp index 718d97cc49..c3084124f1 100644 --- a/src/openrct2/core/FileScanner.cpp +++ b/src/openrct2/core/FileScanner.cpp @@ -227,11 +227,11 @@ public: void GetDirectoryChildren(std::vector& children, const std::string& path) override { - std::string pattern = path + "\\*"; - wchar_t* wPattern = utf8_to_widechar(pattern.c_str()); + auto pattern = path + "\\*"; + auto wPattern = String::ToUtf16(pattern.c_str()); WIN32_FIND_DATAW findData; - HANDLE hFile = FindFirstFileW(wPattern, &findData); + HANDLE hFile = FindFirstFileW(wPattern.c_str(), &findData); if (hFile != INVALID_HANDLE_VALUE) { do @@ -244,8 +244,6 @@ public: } while (FindNextFileW(hFile, &findData)); FindClose(hFile); } - - Memory::Free(wPattern); } private: @@ -253,10 +251,7 @@ private: { DirectoryChild result; - utf8* name = widechar_to_utf8(child->cFileName); - result.Name = std::string(name); - Memory::Free(name); - + result.Name = String::ToUtf8(child->cFileName); if (child->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { result.Type = DIRECTORY_CHILD_TYPE::DC_DIRECTORY; diff --git a/src/openrct2/core/FileStream.hpp b/src/openrct2/core/FileStream.hpp index 0839b9994f..dc4b5e1b83 100644 --- a/src/openrct2/core/FileStream.hpp +++ b/src/openrct2/core/FileStream.hpp @@ -70,11 +70,9 @@ public: } #ifdef _WIN32 - wchar_t* pathW = utf8_to_widechar(path); - wchar_t* modeW = utf8_to_widechar(mode); - _file = _wfopen(pathW, modeW); - free(pathW); - free(modeW); + auto pathW = String::ToUtf16(path); + auto modeW = String::ToUtf16(mode); + _file = _wfopen(pathW.c_str(), modeW.c_str()); #else if (fileMode == FILE_MODE_OPEN) { diff --git a/src/openrct2/core/Path.cpp b/src/openrct2/core/Path.cpp index 35064173d0..8dfaf7f3e2 100644 --- a/src/openrct2/core/Path.cpp +++ b/src/openrct2/core/Path.cpp @@ -171,19 +171,17 @@ namespace Path utf8* GetAbsolute(utf8* buffer, size_t bufferSize, const utf8* relativePath) { #ifdef _WIN32 - wchar_t* relativePathW = utf8_to_widechar(relativePath); + auto relativePathW = String::ToUtf16(relativePath); wchar_t absolutePathW[MAX_PATH]; - DWORD length = GetFullPathNameW(relativePathW, (DWORD)std::size(absolutePathW), absolutePathW, nullptr); - Memory::Free(relativePathW); + DWORD length = GetFullPathNameW(relativePathW.c_str(), (DWORD)std::size(absolutePathW), absolutePathW, nullptr); if (length == 0) { return String::Set(buffer, bufferSize, relativePath); } else { - utf8* absolutePath = widechar_to_utf8(absolutePathW); - String::Set(buffer, bufferSize, absolutePath); - Memory::Free(absolutePath); + auto absolutePath = String::ToUtf8(absolutePathW); + String::Set(buffer, bufferSize, absolutePath.c_str()); return buffer; } #else diff --git a/src/openrct2/localisation/Language.h b/src/openrct2/localisation/Language.h index 17d0340456..d19b0e5eab 100644 --- a/src/openrct2/localisation/Language.h +++ b/src/openrct2/localisation/Language.h @@ -101,8 +101,6 @@ bool utf8_is_codepoint_start(const utf8* text); void utf8_remove_format_codes(utf8* text, bool allowcolours); int32_t utf8_get_codepoint_length(int32_t codepoint); int32_t utf8_length(const utf8* text); -wchar_t* utf8_to_widechar(const utf8* src); -utf8* widechar_to_utf8(const wchar_t* src); std::string rct2_to_utf8(const std::string_view& src, RCT2LanguageId languageId); std::string utf8_to_rct2(const std::string_view& src); diff --git a/src/openrct2/localisation/UTF8.cpp b/src/openrct2/localisation/UTF8.cpp index 708e8df85d..b91c929d18 100644 --- a/src/openrct2/localisation/UTF8.cpp +++ b/src/openrct2/localisation/UTF8.cpp @@ -137,44 +137,6 @@ int32_t utf8_length(const utf8* text) return count; } -wchar_t* utf8_to_widechar(const utf8* src) -{ - wchar_t* result = (wchar_t*)malloc((utf8_length(src) + 1) * sizeof(wchar_t)); - wchar_t* dst = result; - - const utf8* ch = src; - int32_t codepoint; - while ((codepoint = utf8_get_next(ch, &ch)) != 0) - { - if ((uint32_t)codepoint > 0xFFFF) - { - *dst++ = '?'; - } - else - { - *dst++ = codepoint; - } - } - *dst = 0; - - return result; -} - -utf8* widechar_to_utf8(const wchar_t* src) -{ - utf8* result = (utf8*)malloc((wcslen(src) * 4) + 1); - utf8* dst = result; - - for (; *src != 0; src++) - { - dst = utf8_write_codepoint(dst, *src); - } - *dst++ = 0; - - size_t size = (size_t)(dst - result); - return (utf8*)realloc(result, size); -} - /** * Returns a pointer to the null terminator of the given UTF-8 string. */ diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index 80e2d32d51..a4ecd1d205 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -1356,8 +1356,8 @@ void Network::BeginChatLog() _chatLogPath = BeginLog(directory, "", _chatLogFilenameFormat); # if defined(_WIN32) && !defined(__MINGW32__) - auto pathW = std::unique_ptr(utf8_to_widechar(_chatLogPath.c_str())); - _chat_log_fs.open(pathW.get(), std::ios::out | std::ios::app); + auto pathW = String::ToUtf16(_chatLogPath.c_str()); + _chat_log_fs.open(pathW.c_str(), std::ios::out | std::ios::app); # else _chat_log_fs.open(_chatLogPath, std::ios::out | std::ios::app); # endif @@ -1382,8 +1382,8 @@ void Network::BeginServerLog() _serverLogPath = BeginLog(directory, ServerName, _serverLogFilenameFormat); # if defined(_WIN32) && !defined(__MINGW32__) - auto pathW = std::unique_ptr(utf8_to_widechar(_serverLogPath.c_str())); - _server_log_fs.open(pathW.get(), std::ios::out | std::ios::app | std::ios::binary); + auto pathW = String::ToUtf16(_serverLogPath.c_str()); + _server_log_fs.open(pathW.c_str(), std::ios::out | std::ios::app | std::ios::binary); # else _server_log_fs.open(_serverLogPath, std::ios::out | std::ios::app | std::ios::binary); # endif diff --git a/src/openrct2/platform/Crash.cpp b/src/openrct2/platform/Crash.cpp index 45b0dd0525..6d6fc6bf7c 100644 --- a/src/openrct2/platform/Crash.cpp +++ b/src/openrct2/platform/Crash.cpp @@ -150,18 +150,17 @@ static bool OnCrash( wprintf(L"Commit: %s\n", _wszCommitSha1Short); bool savedGameDumped = false; - utf8* saveFilePathUTF8 = widechar_to_utf8(saveFilePath); + auto saveFilePathUTF8 = String::ToUtf8(saveFilePath); try { auto exporter = std::make_unique(); exporter->Export(); - exporter->SaveGame(saveFilePathUTF8); + exporter->SaveGame(saveFilePathUTF8.c_str()); savedGameDumped = true; } catch (const std::exception&) { } - free(saveFilePathUTF8); // Compress the save if (savedGameDumped) @@ -181,19 +180,16 @@ static bool OnCrash( fclose(dest); } - utf8* configFilePathUTF8 = widechar_to_utf8(configFilePath); - if (config_save(configFilePathUTF8)) + auto configFilePathUTF8 = String::ToUtf8(configFilePath); + if (config_save(configFilePathUTF8.c_str())) { uploadFiles[L"attachment_config.ini"] = configFilePath; } - free(configFilePathUTF8); std::string screenshotPath = screenshot_dump(); if (!screenshotPath.empty()) { - wchar_t* screenshotPathWchar = utf8_to_widechar(screenshotPath.c_str()); - auto screenshotPathW = std::wstring(screenshotPathWchar); - free(screenshotPathWchar); + auto screenshotPathW = String::ToUtf16(screenshotPath.c_str()); uploadFiles[L"attachment_screenshot.png"] = screenshotPathW; } @@ -270,11 +266,7 @@ static std::wstring GetDumpDirectory() { char userDirectory[MAX_PATH]; platform_get_user_directory(userDirectory, nullptr, sizeof(userDirectory)); - - wchar_t* userDirectoryW = utf8_to_widechar(userDirectory); - auto result = std::wstring(userDirectoryW); - free(userDirectoryW); - + auto result = String::ToUtf16(userDirectory); return result; } diff --git a/src/openrct2/platform/Posix.cpp b/src/openrct2/platform/Posix.cpp index 733df1b6fc..e31aa4fc0a 100644 --- a/src/openrct2/platform/Posix.cpp +++ b/src/openrct2/platform/Posix.cpp @@ -21,6 +21,7 @@ # include "../OpenRCT2.h" # include "../config/Config.h" # include "../core/Path.hpp" +# include "../core/String.hpp" # include "../localisation/Date.h" # include "../localisation/Language.h" # include "../util/Util.h" @@ -97,20 +98,19 @@ void platform_get_time_local(rct2_time* out_time) static size_t platform_utf8_to_multibyte(const utf8* path, char* buffer, size_t buffer_size) { - wchar_t* wpath = utf8_to_widechar(path); + auto wpath = String::ToUtf16(path); setlocale(LC_CTYPE, "UTF-8"); - size_t len = wcstombs(NULL, wpath, 0); + size_t len = wcstombs(NULL, wpath.c_str(), 0); bool truncated = false; if (len > buffer_size - 1) { truncated = true; len = buffer_size - 1; } - wcstombs(buffer, wpath, len); + wcstombs(buffer, wpath.c_str(), len); buffer[len] = '\0'; if (truncated) log_warning("truncated string %s", buffer); - free(wpath); return len; } @@ -286,19 +286,29 @@ bool platform_directory_delete(const utf8* path) return true; } -utf8* platform_get_absolute_path(const utf8* relative_path, const utf8* base_path) +std::string platform_get_absolute_path(const utf8* relative_path, const utf8* base_path) { - utf8 path[MAX_PATH]; + std::string result; + if (relative_path != nullptr) + { + std::string pathToResolve; + if (base_path == nullptr) + { + pathToResolve = std::string(relative_path); + } + else + { + pathToResolve = std::string(base_path) + std::string("/") + relative_path; + } - if (base_path != nullptr) - { - snprintf(path, MAX_PATH, "%s/%s", base_path, relative_path); + auto realpathResult = realpath(pathToResolve.c_str(), nullptr); + if (realpathResult != nullptr) + { + result = std::string(realpathResult); + free(realpathResult); + } } - else - { - safe_strcpy(path, base_path, MAX_PATH); - } - return realpath(path, NULL); + return result; } bool platform_lock_single_instance() @@ -482,18 +492,15 @@ datetime64 platform_get_datetime_now_utc() return utcNow; } -utf8* platform_get_username() +std::string platform_get_username() { - struct passwd* pw = getpwuid(getuid()); - - if (pw) + std::string result; + auto pw = getpwuid(getuid()); + if (pw != nullptr) { - return pw->pw_name; - } - else - { - return nullptr; + result = std::string(pw->pw_name); } + return result; } bool platform_process_is_elevated() diff --git a/src/openrct2/platform/Windows.cpp b/src/openrct2/platform/Windows.cpp index 78535d3bcf..3e11ec3ce1 100644 --- a/src/openrct2/platform/Windows.cpp +++ b/src/openrct2/platform/Windows.cpp @@ -85,18 +85,16 @@ void platform_get_time_local(rct2_time* out_time) bool platform_file_exists(const utf8* path) { - wchar_t* wPath = utf8_to_widechar(path); - DWORD result = GetFileAttributesW(wPath); + auto wPath = String::ToUtf16(path); + DWORD result = GetFileAttributesW(wPath.c_str()); DWORD error = GetLastError(); - free(wPath); return !(result == INVALID_FILE_ATTRIBUTES && (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND)); } bool platform_directory_exists(const utf8* path) { - wchar_t* wPath = utf8_to_widechar(path); - DWORD dwAttrib = GetFileAttributesW(wPath); - free(wPath); + auto wPath = String::ToUtf16(path); + DWORD dwAttrib = GetFileAttributesW(wPath.c_str()); return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY); } @@ -127,27 +125,20 @@ bool platform_ensure_directory_exists(const utf8* path) if (platform_directory_exists(path)) return 1; - wchar_t* wPath = utf8_to_widechar(path); - BOOL success = CreateDirectoryW(wPath, nullptr); - free(wPath); - return success == TRUE; + auto wPath = String::ToUtf16(path); + auto success = CreateDirectoryW(wPath.c_str(), nullptr); + return success != FALSE; } bool platform_directory_delete(const utf8* path) { - wchar_t pszFrom[MAX_PATH]; - - wchar_t* wPath = utf8_to_widechar(path); - wcsncpy(pszFrom, wPath, MAX_PATH); - - // Needs to be double-null terminated for some weird reason - pszFrom[wcslen(wPath) + 1] = 0; - free(wPath); + // Needs to be double-null terminated as pFrom is a null terminated array of strings + auto wPath = String::ToUtf16(path) + L"\0"; SHFILEOPSTRUCTW fileop; fileop.hwnd = nullptr; // no status display fileop.wFunc = FO_DELETE; // delete operation - fileop.pFrom = pszFrom; // source file name as double null terminated string + fileop.pFrom = wPath.c_str(); // source file name as double null terminated string fileop.pTo = nullptr; // no destination needed fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; // do not prompt the user @@ -189,30 +180,25 @@ int32_t platform_get_drives() bool platform_file_copy(const utf8* srcPath, const utf8* dstPath, bool overwrite) { - wchar_t* wSrcPath = utf8_to_widechar(srcPath); - wchar_t* wDstPath = utf8_to_widechar(dstPath); - BOOL success = CopyFileW(wSrcPath, wDstPath, overwrite ? FALSE : TRUE); - free(wSrcPath); - free(wDstPath); - return success == TRUE; + auto wSrcPath = String::ToUtf16(srcPath); + auto wDstPath = String::ToUtf16(dstPath); + auto success = CopyFileW(wSrcPath.c_str(), wDstPath.c_str(), overwrite ? FALSE : TRUE); + return success != FALSE; } bool platform_file_move(const utf8* srcPath, const utf8* dstPath) { - wchar_t* wSrcPath = utf8_to_widechar(srcPath); - wchar_t* wDstPath = utf8_to_widechar(dstPath); - BOOL success = MoveFileW(wSrcPath, wDstPath); - free(wSrcPath); - free(wDstPath); - return success == TRUE; + auto wSrcPath = String::ToUtf16(srcPath); + auto wDstPath = String::ToUtf16(dstPath); + auto success = MoveFileW(wSrcPath.c_str(), wDstPath.c_str()); + return success != FALSE; } bool platform_file_delete(const utf8* path) { - wchar_t* wPath = utf8_to_widechar(path); - BOOL success = DeleteFileW(wPath); - free(wPath); - return success == TRUE; + auto wPath = String::ToUtf16(path); + auto success = DeleteFileW(wPath.c_str()); + return success != FALSE; } bool platform_get_steam_path(utf8* outPath, size_t outSize) @@ -236,10 +222,9 @@ bool platform_get_steam_path(utf8* outPath, size_t outSize) result = RegQueryValueExW(hKey, L"SteamPath", nullptr, &type, (LPBYTE)wSteamPath, &size); if (result == ERROR_SUCCESS) { - utf8* utf8SteamPath = widechar_to_utf8(wSteamPath); - safe_strcpy(outPath, utf8SteamPath, outSize); + auto utf8SteamPath = String::ToUtf8(wSteamPath); + safe_strcpy(outPath, utf8SteamPath.c_str(), outSize); safe_strcat_path(outPath, "steamapps\\common", outSize); - free(utf8SteamPath); } free(wSteamPath); RegCloseKey(hKey); @@ -340,24 +325,22 @@ uint16_t platform_get_locale_language() time_t platform_file_get_modified_time(const utf8* path) { - WIN32_FILE_ATTRIBUTE_DATA data; - - wchar_t* wPath = utf8_to_widechar(path); - BOOL result = GetFileAttributesExW(wPath, GetFileExInfoStandard, &data); - free(wPath); - - if (!result) - return 0; - - FILETIME localFileTime; - result = FileTimeToLocalFileTime(&data.ftLastWriteTime, &localFileTime); - if (!result) - return 0; - - ULARGE_INTEGER ull; - ull.LowPart = localFileTime.dwLowDateTime; - ull.HighPart = localFileTime.dwHighDateTime; - return ull.QuadPart / 10000000ULL - 11644473600ULL; + WIN32_FILE_ATTRIBUTE_DATA data{}; + auto wPath = String::ToUtf16(path); + auto result = GetFileAttributesExW(wPath.c_str(), GetFileExInfoStandard, &data); + if (result != FALSE) + { + FILETIME localFileTime{}; + result = FileTimeToLocalFileTime(&data.ftLastWriteTime, &localFileTime); + if (result != FALSE) + { + ULARGE_INTEGER ull{}; + ull.LowPart = localFileTime.dwLowDateTime; + ull.HighPart = localFileTime.dwHighDateTime; + return ull.QuadPart / 10000000ULL - 11644473600ULL; + } + } + return 0; } uint8_t platform_get_locale_currency() @@ -468,9 +451,8 @@ bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size) if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Fonts, 0, nullptr, &fontFolder))) { // Convert wchar to utf8, then copy the font folder path to the buffer. - utf8* outPathTemp = widechar_to_utf8(fontFolder); - safe_strcpy(buffer, outPathTemp, size); - free(outPathTemp); + auto outPathTemp = String::ToUtf8(fontFolder); + safe_strcpy(buffer, outPathTemp.c_str(), size); CoTaskMemFree(fontFolder); @@ -491,24 +473,30 @@ bool platform_get_font_path(TTFFontDescriptor* font, utf8* buffer, size_t size) } # endif // NO_TTF -utf8* platform_get_absolute_path(const utf8* relativePath, const utf8* basePath) +std::string platform_get_absolute_path(const utf8* relativePath, const utf8* basePath) { - utf8 path[MAX_PATH]; - safe_strcpy(path, basePath, sizeof(path)); - safe_strcat_path(path, relativePath, sizeof(path)); - - wchar_t* pathW = utf8_to_widechar(path); - wchar_t fullPathW[MAX_PATH]; - DWORD fullPathLen = GetFullPathNameW(pathW, (DWORD)std::size(fullPathW), fullPathW, nullptr); - - free(pathW); - - if (fullPathLen == 0) + std::string result; + if (relativePath != nullptr) { - return nullptr; - } + std::string pathToResolve; + if (basePath == nullptr) + { + pathToResolve = std::string(relativePath); + } + else + { + pathToResolve = std::string(basePath) + std::string("\\") + relativePath; + } - return widechar_to_utf8(fullPathW); + auto pathToResolveW = String::ToUtf16(pathToResolve); + wchar_t fullPathW[MAX_PATH]{}; + auto fullPathLen = GetFullPathNameW(pathToResolveW.c_str(), (DWORD)std::size(fullPathW), fullPathW, nullptr); + if (fullPathLen != 0) + { + result = String::ToUtf8(fullPathW); + } + } + return result; } datetime64 platform_get_datetime_now_utc() @@ -524,18 +512,16 @@ datetime64 platform_get_datetime_now_utc() return utcNow; } -utf8* platform_get_username() +std::string platform_get_username() { - static wchar_t usernameW[UNLEN + 1]; + std::string result; + wchar_t usernameW[UNLEN + 1]{}; DWORD usernameLength = UNLEN + 1; - if (!GetUserNameW(usernameW, &usernameLength)) + if (GetUserNameW(usernameW, &usernameLength)) { - return nullptr; + result = String::ToUtf8(usernameW); } - - static std::string username; - username = widechar_to_utf8(usernameW); - return username.data(); + return result; } bool platform_process_is_elevated() @@ -565,15 +551,11 @@ bool platform_process_is_elevated() # define SOFTWARE_CLASSES L"Software\\Classes" # define MUI_CACHE L"Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache" -static void get_progIdName(wchar_t* dst, const utf8* extension) +static std::wstring get_progIdName(const std::string_view& extension) { - utf8 progIdName[128]; - safe_strcpy(progIdName, OPENRCT2_NAME, sizeof(progIdName)); - safe_strcat(progIdName, extension, sizeof(progIdName)); - - wchar_t* progIdNameW = utf8_to_widechar(progIdName); - lstrcpyW(dst, progIdNameW); - free(progIdNameW); + auto progIdName = std::string(OPENRCT2_NAME) + std::string(extension); + auto progIdNameW = String::ToUtf16(progIdName); + return progIdNameW; } static bool windows_setup_file_association( @@ -587,13 +569,11 @@ static bool windows_setup_file_association( GetModuleFileNameW(nullptr, exePathW, (DWORD)std::size(exePathW)); GetModuleFileNameW(plaform_get_dll_module(), dllPathW, (DWORD)std::size(dllPathW)); - wchar_t* extensionW = utf8_to_widechar(extension); - wchar_t* fileTypeTextW = utf8_to_widechar(fileTypeText); - wchar_t* commandTextW = utf8_to_widechar(commandText); - wchar_t* commandArgsW = utf8_to_widechar(commandArgs); - - wchar_t progIdNameW[128]; - get_progIdName(progIdNameW, extension); + auto extensionW = String::ToUtf16(extension); + auto fileTypeTextW = String::ToUtf16(fileTypeText); + auto commandTextW = String::ToUtf16(commandText); + auto commandArgsW = String::ToUtf16(commandArgs); + auto progIdNameW = get_progIdName(extension); bool result = false; HKEY hKey = nullptr; @@ -606,18 +586,18 @@ static bool windows_setup_file_association( } // [hRootKey\.ext] - if (RegSetValueW(hRootKey, extensionW, REG_SZ, progIdNameW, 0) != ERROR_SUCCESS) + if (RegSetValueW(hRootKey, extensionW.c_str(), REG_SZ, progIdNameW.c_str(), 0) != ERROR_SUCCESS) { goto fail; } - if (RegCreateKeyW(hRootKey, progIdNameW, &hKey) != ERROR_SUCCESS) + if (RegCreateKeyW(hRootKey, progIdNameW.c_str(), &hKey) != ERROR_SUCCESS) { goto fail; } // [hRootKey\OpenRCT2.ext] - if (RegSetValueW(hKey, nullptr, REG_SZ, fileTypeTextW, 0) != ERROR_SUCCESS) + if (RegSetValueW(hKey, nullptr, REG_SZ, fileTypeTextW.c_str(), 0) != ERROR_SUCCESS) { goto fail; } @@ -637,14 +617,14 @@ static bool windows_setup_file_association( } // [hRootKey\OpenRCT2.sv6\shell\open] - if (RegSetValueW(hKey, L"shell\\open", REG_SZ, commandTextW, 0) != ERROR_SUCCESS) + if (RegSetValueW(hKey, L"shell\\open", REG_SZ, commandTextW.c_str(), 0) != ERROR_SUCCESS) { goto fail; } // [hRootKey\OpenRCT2.sv6\shell\open\command] wchar_t szCommandW[MAX_PATH]; - printResult = swprintf_s(szCommandW, MAX_PATH, L"\"%s\" %s", exePathW, commandArgsW); + printResult = swprintf_s(szCommandW, MAX_PATH, L"\"%s\" %s", exePathW, commandArgsW.c_str()); assert(printResult >= 0); if (RegSetValueW(hKey, L"shell\\open\\command", REG_SZ, szCommandW, 0) != ERROR_SUCCESS) { @@ -653,10 +633,6 @@ static bool windows_setup_file_association( result = true; fail: - free(extensionW); - free(fileTypeTextW); - free(commandTextW); - free(commandArgsW); RegCloseKey(hKey); RegCloseKey(hRootKey); return result; @@ -672,9 +648,8 @@ static void windows_remove_file_association(const utf8* extension) RegDeleteTreeA(hRootKey, extension); // [hRootKey\OpenRCT2.ext] - wchar_t progIdName[128]; - get_progIdName(progIdName, extension); - RegDeleteTreeW(hRootKey, progIdName); + auto progIdName = get_progIdName(extension); + RegDeleteTreeW(hRootKey, progIdName.c_str()); RegCloseKey(hRootKey); } diff --git a/src/openrct2/platform/platform.h b/src/openrct2/platform/platform.h index bad0ad63eb..5a43d04b73 100644 --- a/src/openrct2/platform/platform.h +++ b/src/openrct2/platform/platform.h @@ -99,7 +99,7 @@ bool platform_original_rct1_data_exists(const utf8* path); time_t platform_file_get_modified_time(const utf8* path); bool platform_ensure_directory_exists(const utf8* path); bool platform_directory_delete(const utf8* path); -utf8* platform_get_absolute_path(const utf8* relative_path, const utf8* base_path); +std::string platform_get_absolute_path(const utf8* relative_path, const utf8* base_path); bool platform_lock_single_instance(); bool platform_place_string_on_clipboard(utf8* target); @@ -113,7 +113,7 @@ uint32_t platform_get_ticks(); void platform_sleep(uint32_t ms); void platform_get_openrct_data_path(utf8* outPath, size_t outSize); void platform_get_user_directory(utf8* outPath, const utf8* subDirectory, size_t outSize); -utf8* platform_get_username(); +std::string platform_get_username(); bool platform_open_common_file_dialog(utf8* outFilename, file_dialog_desc* desc, size_t outSize); utf8* platform_open_directory_browser(const utf8* title); uint8_t platform_get_locale_currency();