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:
Zephyron
2025-11-01 21:56:37 +10:00
parent ef14da5014
commit 3d0ccc1db1
4 changed files with 66 additions and 2 deletions

View File

@@ -512,6 +512,38 @@ if (WIN32 AND QT_VERSION VERSION_GREATER_EQUAL 6)
COMMAND ${CMAKE_COMMAND} -E make_directory "${CITRON_EXE_DIR}/user"
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()
if (CITRON_USE_BUNDLED_QT)

View File

@@ -83,10 +83,27 @@ UpdaterService::~UpdaterService() {
void UpdaterService::InitializeSSL() {
LOG_INFO(Frontend, "Attempting to initialize SSL support...");
// Check if SSL is supported
if (!QSslSocket::supportsSsl()) {
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;
}
LOG_INFO(Frontend, "SSL library version: {}", QSslSocket::sslLibraryVersionString().toStdString());
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
auto certs = QSslConfiguration::systemCaCertificates();
if (!certs.isEmpty()) {
@@ -612,9 +629,11 @@ bool UpdaterService::LaunchUpdateHelper() {
// Launch the batch script as a detached process
QString script_path_str = QString::fromStdString(script_path.string());
QStringList arguments;
arguments << QStringLiteral("/C");
arguments << script_path_str;
// 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) {
LOG_INFO(Frontend, "Update helper script launched successfully");

View File

@@ -53,6 +53,10 @@ public:
static bool HasStagedUpdate(const std::filesystem::path& app_directory);
static bool ApplyStagedUpdate(const std::filesystem::path& app_directory);
#ifdef _WIN32
bool LaunchUpdateHelper();
#endif
signals:
void UpdateCheckCompleted(bool has_update, const UpdateInfo& update_info);
void UpdateDownloadProgress(int percentage, qint64 bytes_received, qint64 bytes_total);
@@ -80,7 +84,6 @@ private:
bool CreateBackup();
bool RestoreBackup();
bool CreateUpdateHelperScript(const std::filesystem::path& staging_path);
bool LaunchUpdateHelper();
#endif
bool CleanupFiles();
std::filesystem::path GetTempDirectory() const;

View File

@@ -49,8 +49,14 @@ add_library(core STATIC
file_sys/common_funcs.h
file_sys/content_archive.cpp
file_sys/content_archive.h
file_sys/content_exporter.cpp
file_sys/content_exporter.h
file_sys/control_metadata.cpp
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/fs_directory.h
file_sys/fs_file.h
@@ -1183,10 +1189,14 @@ add_library(core STATIC
loader/nca.h
loader/nro.cpp
loader/nro.h
loader/nsd.cpp
loader/nsd.h
loader/nso.cpp
loader/nso.h
loader/nsp.cpp
loader/nsp.h
loader/xcd.cpp
loader/xcd.h
loader/xci.cpp
loader/xci.h
memory.cpp