Merge pull request #3314 from thunder2/get-main-executable-path

Moved Windows specific code for getting main executable path from ret…
This commit is contained in:
csoler 2026-09-11 20:09:55 +02:00 committed by GitHub
commit e43d23f1af
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 123 additions and 51 deletions

View File

@ -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})

View File

@ -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<wchar_t> 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<DWORD>(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);

View File

@ -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 ########################################

View File

@ -0,0 +1,85 @@
/*******************************************************************************
* util/retroshare-service_path.cpp *
* *
* Copyright (C) 2026 Retroshare Team <retroshare.project@gmail.com> *
* *
* 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 <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#ifdef WINDOWS_SYS
#include <windows.h>
#include <vector>
#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<wchar_t> 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<DWORD>(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;
}

View File

@ -0,0 +1,26 @@
/*******************************************************************************
* util/retroshare-service_path.h *
* *
* Copyright (C) 2026 Retroshare Team <retroshare.project@gmail.com> *
* *
* 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 <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
#pragma once
#include <string>
/** Get file path of the main executable */
std::string getMainExecutablePath(const char* argv0);