mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-19 10:43:33 +00:00
Fix Windows auto updater with deferred update helper and TLS support
Windows auto updater failed due to: 1. File locking - can't overwrite running .exe files 2. Missing Qt 6 TLS plugins - can't connect via HTTPS Solution: - Implement helper batch script that applies updates after app exits - Automate TLS plugin copying in CMake (qschannelbackend.dll, qopensslbackend.dll) - Add enhanced SSL debugging and error messages Windows updates now work. Linux continues to work as before. Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
@@ -512,6 +512,38 @@ if (WIN32 AND QT_VERSION VERSION_GREATER_EQUAL 6)
|
|||||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${CITRON_EXE_DIR}/user"
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${CITRON_EXE_DIR}/user"
|
||||||
COMMENT "Creating portable user directory"
|
COMMENT "Creating portable user directory"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Copy Qt TLS plugins for SSL/TLS support (required for auto updater and HTTPS)
|
||||||
|
# Qt 6 uses a plugin architecture for TLS backends
|
||||||
|
if (CITRON_USE_AUTO_UPDATER OR ENABLE_OPENSSL)
|
||||||
|
set(Qt6_TLS_PLUGINS_DIR "${Qt6_DIR}/../../../plugins/tls")
|
||||||
|
|
||||||
|
# Create tls directory
|
||||||
|
add_custom_command(TARGET citron POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${CITRON_EXE_DIR}/tls"
|
||||||
|
COMMENT "Creating TLS plugin directory for SSL support"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Copy Windows native Schannel backend (no external dependencies)
|
||||||
|
if (EXISTS "${Qt6_TLS_PLUGINS_DIR}/qschannelbackend.dll")
|
||||||
|
add_custom_command(TARGET citron POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${Qt6_TLS_PLUGINS_DIR}/qschannelbackend.dll"
|
||||||
|
"${CITRON_EXE_DIR}/tls/qschannelbackend.dll"
|
||||||
|
COMMENT "Copying Qt Schannel TLS plugin (Windows native SSL)"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Copy OpenSSL backend as fallback (requires OpenSSL DLLs)
|
||||||
|
if (EXISTS "${Qt6_TLS_PLUGINS_DIR}/qopensslbackend.dll")
|
||||||
|
add_custom_command(TARGET citron POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
"${Qt6_TLS_PLUGINS_DIR}/qopensslbackend.dll"
|
||||||
|
"${CITRON_EXE_DIR}/tls/qopensslbackend.dll"
|
||||||
|
COMMENT "Copying Qt OpenSSL TLS plugin (fallback)"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CITRON_USE_BUNDLED_QT)
|
if (CITRON_USE_BUNDLED_QT)
|
||||||
|
|||||||
@@ -83,10 +83,27 @@ UpdaterService::~UpdaterService() {
|
|||||||
|
|
||||||
void UpdaterService::InitializeSSL() {
|
void UpdaterService::InitializeSSL() {
|
||||||
LOG_INFO(Frontend, "Attempting to initialize SSL support...");
|
LOG_INFO(Frontend, "Attempting to initialize SSL support...");
|
||||||
|
|
||||||
|
// Check if SSL is supported
|
||||||
if (!QSslSocket::supportsSsl()) {
|
if (!QSslSocket::supportsSsl()) {
|
||||||
LOG_WARNING(Frontend, "SSL support not available");
|
LOG_WARNING(Frontend, "SSL support not available");
|
||||||
|
LOG_WARNING(Frontend, "Build-time SSL version: {}", QSslSocket::sslLibraryBuildVersionString().toStdString());
|
||||||
|
LOG_WARNING(Frontend, "Runtime SSL version: {}", QSslSocket::sslLibraryVersionString().toStdString());
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Try to provide helpful information about missing DLLs
|
||||||
|
std::filesystem::path app_dir = std::filesystem::path(QCoreApplication::applicationDirPath().toStdString());
|
||||||
|
std::filesystem::path crypto_dll = app_dir / "libcrypto-3-x64.dll";
|
||||||
|
std::filesystem::path ssl_dll = app_dir / "libssl-3-x64.dll";
|
||||||
|
|
||||||
|
LOG_WARNING(Frontend, "libcrypto-3-x64.dll exists: {}", std::filesystem::exists(crypto_dll));
|
||||||
|
LOG_WARNING(Frontend, "libssl-3-x64.dll exists: {}", std::filesystem::exists(ssl_dll));
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_INFO(Frontend, "SSL library version: {}", QSslSocket::sslLibraryVersionString().toStdString());
|
||||||
|
|
||||||
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
|
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
|
||||||
auto certs = QSslConfiguration::systemCaCertificates();
|
auto certs = QSslConfiguration::systemCaCertificates();
|
||||||
if (!certs.isEmpty()) {
|
if (!certs.isEmpty()) {
|
||||||
@@ -612,9 +629,11 @@ bool UpdaterService::LaunchUpdateHelper() {
|
|||||||
// Launch the batch script as a detached process
|
// Launch the batch script as a detached process
|
||||||
QString script_path_str = QString::fromStdString(script_path.string());
|
QString script_path_str = QString::fromStdString(script_path.string());
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
|
arguments << QStringLiteral("/C");
|
||||||
|
arguments << script_path_str;
|
||||||
|
|
||||||
// Use cmd.exe to run the batch file in a hidden window
|
// Use cmd.exe to run the batch file in a hidden window
|
||||||
bool launched = QProcess::startDetached("cmd.exe", QStringList() << "/C" << script_path_str);
|
bool launched = QProcess::startDetached(QStringLiteral("cmd.exe"), arguments);
|
||||||
|
|
||||||
if (launched) {
|
if (launched) {
|
||||||
LOG_INFO(Frontend, "Update helper script launched successfully");
|
LOG_INFO(Frontend, "Update helper script launched successfully");
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ public:
|
|||||||
static bool HasStagedUpdate(const std::filesystem::path& app_directory);
|
static bool HasStagedUpdate(const std::filesystem::path& app_directory);
|
||||||
static bool ApplyStagedUpdate(const std::filesystem::path& app_directory);
|
static bool ApplyStagedUpdate(const std::filesystem::path& app_directory);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
bool LaunchUpdateHelper();
|
||||||
|
#endif
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void UpdateCheckCompleted(bool has_update, const UpdateInfo& update_info);
|
void UpdateCheckCompleted(bool has_update, const UpdateInfo& update_info);
|
||||||
void UpdateDownloadProgress(int percentage, qint64 bytes_received, qint64 bytes_total);
|
void UpdateDownloadProgress(int percentage, qint64 bytes_received, qint64 bytes_total);
|
||||||
@@ -80,7 +84,6 @@ private:
|
|||||||
bool CreateBackup();
|
bool CreateBackup();
|
||||||
bool RestoreBackup();
|
bool RestoreBackup();
|
||||||
bool CreateUpdateHelperScript(const std::filesystem::path& staging_path);
|
bool CreateUpdateHelperScript(const std::filesystem::path& staging_path);
|
||||||
bool LaunchUpdateHelper();
|
|
||||||
#endif
|
#endif
|
||||||
bool CleanupFiles();
|
bool CleanupFiles();
|
||||||
std::filesystem::path GetTempDirectory() const;
|
std::filesystem::path GetTempDirectory() const;
|
||||||
|
|||||||
@@ -49,8 +49,14 @@ add_library(core STATIC
|
|||||||
file_sys/common_funcs.h
|
file_sys/common_funcs.h
|
||||||
file_sys/content_archive.cpp
|
file_sys/content_archive.cpp
|
||||||
file_sys/content_archive.h
|
file_sys/content_archive.h
|
||||||
|
file_sys/content_exporter.cpp
|
||||||
|
file_sys/content_exporter.h
|
||||||
file_sys/control_metadata.cpp
|
file_sys/control_metadata.cpp
|
||||||
file_sys/control_metadata.h
|
file_sys/control_metadata.h
|
||||||
|
file_sys/decrypted_nsp.cpp
|
||||||
|
file_sys/decrypted_nsp.h
|
||||||
|
file_sys/decrypted_xci.cpp
|
||||||
|
file_sys/decrypted_xci.h
|
||||||
file_sys/errors.h
|
file_sys/errors.h
|
||||||
file_sys/fs_directory.h
|
file_sys/fs_directory.h
|
||||||
file_sys/fs_file.h
|
file_sys/fs_file.h
|
||||||
@@ -1183,10 +1189,14 @@ add_library(core STATIC
|
|||||||
loader/nca.h
|
loader/nca.h
|
||||||
loader/nro.cpp
|
loader/nro.cpp
|
||||||
loader/nro.h
|
loader/nro.h
|
||||||
|
loader/nsd.cpp
|
||||||
|
loader/nsd.h
|
||||||
loader/nso.cpp
|
loader/nso.cpp
|
||||||
loader/nso.h
|
loader/nso.h
|
||||||
loader/nsp.cpp
|
loader/nsp.cpp
|
||||||
loader/nsp.h
|
loader/nsp.h
|
||||||
|
loader/xcd.cpp
|
||||||
|
loader/xcd.h
|
||||||
loader/xci.cpp
|
loader/xci.cpp
|
||||||
loader/xci.h
|
loader/xci.h
|
||||||
memory.cpp
|
memory.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user