diff --git a/retroshare-service/CMakeLists.txt b/retroshare-service/CMakeLists.txt index c08443deb..4709a6621 100644 --- a/retroshare-service/CMakeLists.txt +++ b/retroshare-service/CMakeLists.txt @@ -90,7 +90,8 @@ endif(RS_DEVELOPMENT_BUILD) list( APPEND RS_SERVICE_SOURCES - src/retroshare-service.cc ) + src/retroshare-service.cc + src/util/retroshare-service_path.cpp ) add_executable(${PROJECT_NAME} ${RS_SERVICE_SOURCES}) diff --git a/retroshare-service/src/retroshare-service.cc b/retroshare-service/src/retroshare-service.cc index 186724a2e..e863460ab 100644 --- a/retroshare-service/src/retroshare-service.cc +++ b/retroshare-service/src/retroshare-service.cc @@ -46,6 +46,7 @@ #include "util/rskbdinput.h" #include "util/rsdir.h" #include "util/rsdebug.h" +#include "util/retroshare-service_path.h" #ifdef RS_JSONAPI # include "retroshare/rsjsonapi.h" @@ -545,56 +546,11 @@ int main(int argc, char* argv[]) #endif /* defined(RS_JSONAPI) && defined(RS_WEBUI) && defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD) */ - std::string mainExecutablePath; -#ifdef WINDOWS_SYS - { - // Use a dynamic buffer to handle paths longer than MAX_PATH safely - std::vector filename(MAX_PATH); - while (true) { - // Clear error state before the call to avoid stale error codes causing infinite loops - SetLastError(ERROR_SUCCESS); - - // Passing NULL retrieves the path of the current executable (.exe) - DWORD result = GetModuleFileNameW(NULL, filename.data(), static_cast(filename.size())); - - // Check for function failure - if (result == 0) { - RsFatal() << "Failed to calculate string size. Error code: " << GetLastError() << std::endl; - return 1; - } - - // If the buffer was too small or truncated, double its size and try again - if (result == filename.size() || GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - filename.resize(filename.size() * 2); - continue; - } - - // Success: path was fully copied - filename.resize(result); // Resize vector to the actual path length - break; - } - - // Calculate the required buffer size for the UTF-8 string - int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, filename.data(), -1, NULL, 0, NULL, NULL); - if (sizeNeeded == 0) { - RsFatal() << "Failed to calculate string size. Error code: " << GetLastError() << std::endl; - return 1; - } - - // Instantiate a std::string with the matching size - mainExecutablePath.resize(sizeNeeded - 1, 0); // -1 excludes the null-terminator - - // Convert UTF-16 to UTF-8 - int result = WideCharToMultiByte(CP_UTF8, 0, filename.data(), -1, &mainExecutablePath[0], sizeNeeded, NULL, NULL); - if (result == 0) { - RsFatal() << "Failed to convert string to UTF-8. Error code: " << GetLastError() << std::endl; - return 1; - } + conf.main_executable_path = getMainExecutablePath(argv[0]); + if (conf.main_executable_path.empty()) { + RsFatal() << "Failed to get executable path" << std::endl; + return 1; } -#else - mainExecutablePath = argv[0]; -#endif - conf.main_executable_path = mainExecutablePath; int initResult = RsInit::InitRetroShare(conf); diff --git a/retroshare-service/src/retroshare-service.pro b/retroshare-service/src/retroshare-service.pro index a5daa285d..aefa3fd31 100644 --- a/retroshare-service/src/retroshare-service.pro +++ b/retroshare-service/src/retroshare-service.pro @@ -24,7 +24,11 @@ TARGET = retroshare-service !include("../../libretroshare/src/use_libretroshare.pri"):error("Including") -SOURCES += retroshare-service.cc +SOURCES += retroshare-service.cc \ + util/retroshare-service_path.cpp + +HEADERS += \ + util/retroshare-service_path.h ################################# Linux ######################################## diff --git a/retroshare-service/src/util/retroshare-service_path.cpp b/retroshare-service/src/util/retroshare-service_path.cpp new file mode 100644 index 000000000..2aa337370 --- /dev/null +++ b/retroshare-service/src/util/retroshare-service_path.cpp @@ -0,0 +1,85 @@ +/******************************************************************************* + * util/retroshare-service_path.cpp * + * * + * Copyright (C) 2026 Retroshare Team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#ifdef WINDOWS_SYS +#include +#include +#include "util/rsdebug.h" +#endif + +#include "retroshare-service_path.h" + +/** Get file path of the main executable */ +std::string getMainExecutablePath(const char *argv0) +{ + std::string mainExecutablePath; + +#ifdef WINDOWS_SYS + // Use a dynamic buffer to handle paths longer than MAX_PATH safely + std::vector filename(MAX_PATH); + while (true) { + // Clear error state before the call to avoid stale error codes causing infinite loops + SetLastError(ERROR_SUCCESS); + + // Passing NULL retrieves the path of the current executable (.exe) + DWORD result = GetModuleFileNameW(NULL, filename.data(), static_cast(filename.size())); + + // Check for function failure + if (result == 0) { + RsFatal() << "Failed to calculate string size. Error code: " << GetLastError() << std::endl; + return std::string(); + } + + // If the buffer was too small or truncated, double its size and try again + if (result == filename.size() || GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + filename.resize(filename.size() * 2); + continue; + } + + // Success: path was fully copied + filename.resize(result); // Resize vector to the actual path length + break; + } + + // Calculate the required buffer size for the UTF-8 string + int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, filename.data(), -1, NULL, 0, NULL, NULL); + if (sizeNeeded == 0) { + RsFatal() << "Failed to calculate string size. Error code: " << GetLastError() << std::endl; + return std::string(); + } + + // Instantiate a std::string with the matching size + mainExecutablePath.resize(sizeNeeded - 1, 0); // -1 excludes the null-terminator + + // Convert UTF-16 to UTF-8 + int result = WideCharToMultiByte(CP_UTF8, 0, filename.data(), -1, &mainExecutablePath[0], sizeNeeded, NULL, NULL); + if (result == 0) { + RsFatal() << "Failed to convert string to UTF-8. Error code: " << GetLastError() << std::endl; + return std::string(); + } + +#else + if (argv0 != nullptr) { + mainExecutablePath = std::string(argv0); + } +#endif + + return mainExecutablePath; +} diff --git a/retroshare-service/src/util/retroshare-service_path.h b/retroshare-service/src/util/retroshare-service_path.h new file mode 100644 index 000000000..610bc806b --- /dev/null +++ b/retroshare-service/src/util/retroshare-service_path.h @@ -0,0 +1,26 @@ +/******************************************************************************* + * util/retroshare-service_path.h * + * * + * Copyright (C) 2026 Retroshare Team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#pragma once + +#include + +/** Get file path of the main executable */ +std::string getMainExecutablePath(const char* argv0);