Page MenuHome GnuPG

No OneTemporary

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4152d7e..c589692 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,78 +1,87 @@
cmake_minimum_required(VERSION 3.16)
set(VERSION "0.0.1")
project(gnupgpass VERSION 0.0.1)
set(QT_MIN_VERSION "5.15.0")
set(KF_MIN_VERSION "5.100.0")
if (QT_MAJOR_VERSION STREQUAL "6")
set(QT_MIN_VERSION "6.6.0")
set(KF_MIN_VERSION "5.240.0")
endif()
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules)
include(KDEInstallDirs)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDECMakeSettings)
include(ECMMarkAsTest)
include(ECMAddTests)
include(FeatureSummary)
include(ECMAddAppIcon)
include(ECMSetupVersion)
include(KDEGitCommitHooks)
include(KDEClangFormat)
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Generate header with version number
ecm_setup_version(${VERSION} VARIABLE_PREFIX GPGPASS VERSION_HEADER
"${CMAKE_CURRENT_BINARY_DIR}/gpgpass_version.h")
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} NO_MODULE COMPONENTS Core Widgets Test)
set_package_properties(Qt6 PROPERTIES
TYPE REQUIRED
PURPOSE "Basic application components"
)
+
+find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} NO_MODULE COMPONENTS DBus)
+
+set(HAVE_QDBUS ${Qt6DBus_FOUND})
+
include_directories(${CMAKE_BINARY_DIR})
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} REQUIRED COMPONENTS
CoreAddons
Prison
IconThemes
I18n
WidgetsAddons
ItemModels
ItemViews
Config
KIO
XmlGui
+ WindowSystem
)
+
+find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} COMPONENTS DBusAddons)
+
if (QT_MAJOR_VERSION STREQUAL "6")
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} REQUIRED COMPONENTS ColorScheme)
find_package(QGpgmeQt6 1.19 CONFIG REQUIRED)
set(KPIM_LIBKLEO_VERSION "6.1.40")
find_package(KPim6Libkleo ${KPIM_LIBKLEO_VERSION} CONFIG REQUIRED)
set(CMAKE_MODULE_PATH ${LIBKLEO_MODULE_PATH} ${CMAKE_MODULE_PATH})
find_package(LibGpgError ${GPG_ERROR_REQUIRED_VERSION} REQUIRED)
else()
find_package(QGpgme 1.19 CONFIG REQUIRED)
find_package(KPim5Libkleo ${KPIM_LIBKLEO_VERSION} CONFIG REQUIRED)
find_package(KF${QT_MAJOR_VERSION} ${KF_MIN_VERSION} REQUIRED COMPONENTS ConfigWidgets)
endif()
add_subdirectory(main)
add_subdirectory(src)
add_subdirectory(autotests)
ki18n_install(po)
install(FILES org.gnupg.gpgpass.desktop DESTINATION ${KDE_INSTALL_APPDIR})
install(FILES org.gnupg.gpgpass.metainfo.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
install(FILES artwork/sc-gpgpass.svg DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps RENAME org.gnupg.gpgpass.svg)
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt
index d5b8d3d..7fb276b 100644
--- a/main/CMakeLists.txt
+++ b/main/CMakeLists.txt
@@ -1,26 +1,26 @@
add_executable(gpgpass)
-target_link_libraries(gpgpass gpgpass_internal KF${QT_MAJOR_VERSION}::IconThemes)
+target_link_libraries(gpgpass gpgpass_internal KF${QT_MAJOR_VERSION}::IconThemes KF${QT_MAJOR_VERSION}::WindowSystem)
if (QT_MAJOR_VERSION STREQUAL "6")
target_link_libraries(gpgpass KF${QT_MAJOR_VERSION}::ColorScheme KPim6::Libkleo)
endif()
ecm_add_app_icon(GPGPASS_ICONS ICONS ${CMAKE_SOURCE_DIR}/artwork/sc-gpgpass.svg ${CMAKE_SOURCE_DIR}/artwork/32-gpgpass.png ${CMAKE_SOURCE_DIR}/artwork/64-gpgpass.png ${CMAKE_SOURCE_DIR}/artwork/256-gpgpass.png)
target_sources(gpgpass PRIVATE
main.cpp
aboutdata.cpp
gpgpass.qrc
${GPGPASS_ICONS}
)
target_compile_definitions(gpgpass PRIVATE QT_NO_TRANSLATION)
if(WIN32)
configure_file(versioninfo.rc.in versioninfo.rc)
configure_file(gpgpass.w32-manifest.in gpgpass.w32-manifest)
target_sources(gpgpass PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc
${CMAKE_CURRENT_BINARY_DIR}/gpgpass.w32-manifest
)
endif()
install(TARGETS gpgpass ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/main/main.cpp b/main/main.cpp
index d7d390f..6ae3bb4 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -1,69 +1,113 @@
/*
SPDX-FileCopyrightText: 2014-2023 Anne Jan Brouwer <brouwer@annejan.com>
SPDX-FileCopyrightText: 2023 g10 Code GmbH
SPDX-FileContributor: Sune Stolborg Vuorela <sune@vuorela.dk>
SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "aboutdata.h"
+#include "kuniqueservice.h"
#include "widgets/mainwindow.h"
#include <QApplication>
+#include <QCommandLineParser>
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
#include <KColorSchemeManager>
#endif
#include <KIconLoader>
#include <KLocalizedString>
+#include <KMessageBox>
+#include <KWindowSystem>
#include <gpgpass_version.h>
#ifdef Q_OS_WINDOWS
#include <windows.h>
#endif
#include <sys/stat.h>
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
// allow darkmode
#if defined(Q_OS_WIN)
if (!qEnvironmentVariableIsSet("QT_QPA_PLATFORM")) {
qputenv("QT_QPA_PLATFORM", "windows:darkmode=1");
}
#endif
QApplication app(argc, argv);
KLocalizedString::setApplicationDomain("gpgpass");
AboutData aboutData;
KAboutData::setApplicationData(aboutData);
+ KUniqueService service;
+
Q_INIT_RESOURCE(resources);
#ifdef Q_OS_WINDOWS
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
}
QApplication::setWindowIcon(QIcon(QStringLiteral(":/artwork/64-gpgpass.png")));
#else
QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("org.gnupg.gpgpass")));
#endif
auto w = new MainWindow;
+ QObject::connect(&service, &KUniqueService::activateRequested, &app, [&service, w](const QStringList &arguments, const QString &workingDirectory) {
+ Q_UNUSED(workingDirectory);
+ QCommandLineParser parser;
+
+ QString err;
+ if (!arguments.isEmpty() && !parser.parse(arguments)) {
+ err = parser.errorText();
+ } else if (arguments.isEmpty()) {
+ // KDBusServices omits the application name if no other
+ // arguments are provided. In that case the parser prints
+ // a warning.
+ parser.parse(QStringList() << QCoreApplication::applicationFilePath());
+ }
+
+ if (err.isEmpty()) {
+#ifdef Q_OS_WIN
+ if (w->isMinimized()) {
+ w->raise();
+ } else if (w->isVisible()) {
+ w->raise();
+#else
+ if (w->isVisible()) {
+ KWindowSystem::updateStartupId(w->windowHandle());
+ KWindowSystem::activateWindow(w->windowHandle());
+#endif
+ } else {
+ w->show();
+ }
+ }
+
+ if (!err.isEmpty()) {
+ KMessageBox::error(nullptr, err.toHtmlEscaped(), i18nc("@title:window", "Failed to execute command"));
+ service.setExitValue(1);
+ return;
+ }
+ service.setExitValue(0);
+ });
+
// ensure KIconThemes is loaded for rcc icons
KIconLoader::global()->hasIcon(QString{});
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
KColorSchemeManager::instance();
#endif
w->show();
return app.exec();
}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ca69d61..cac33de 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,127 +1,135 @@
# let's put most of the "meat" in a static library this way, we can also unit
# test parts of it
add_library(gpgpass_internal STATIC)
target_sources(gpgpass_internal PRIVATE
../resources.qrc
clipboardhelper.cpp
clipboardhelper.h
gpgmehelpers.h
gpgmehelpers.h
+ kuniqueservice.cpp
+ kuniqueservice.h
passentry.cpp
passentry.h
passphrasegenerator.cpp
passphrasegenerator.h
passwordhealth.cpp
passwordhealth.h
passwordgenerator.cpp
passwordgenerator.h
rootfoldersmanager.cpp
rootfoldersmanager.h
userinfo.cpp
userinfo.h
util.cpp
util.h
job/directoryreencryptjob.cpp
job/directoryreencryptjob.h
job/fileencryptjob.cpp
job/fileencryptjob.h
job/filedecryptjob.cpp
job/filedecryptjob.h
job/filereencryptjob.cpp
job/filereencryptjob.h
conf/configuredialog.cpp
conf/configuredialog.h
conf/generalconfigurationpage.cpp
conf/generalconfigurationpage.h
conf/gpgpassconfigmodule.cpp
conf/gpgpassconfigmodule.h
conf/gpgpasspageconfigdialog.cpp
conf/gpgpasspageconfigdialog.h
conf/rootfoldersconfigurationpage.cpp
conf/rootfoldersconfigurationpage.h
conf/templateconfigurationpage.cpp
conf/templateconfigurationpage.h
models/addfileinfoproxy.cpp
models/addfileinfoproxy.h
models/storemodel.cpp
models/storemodel.h
models/userslistmodel.cpp
models/userslistmodel.h
models/rootfoldersmodel.cpp
models/rootfoldersmodel.h
widgets/adjustingscrollarea.cpp
widgets/adjustingscrollarea.h
widgets/deselectabletreeview.h
widgets/formtextinput.cpp
widgets/formtextinput.h
widgets/kplaceholderwidget.cpp
widgets/kplaceholderwidget.h
widgets/mainwindow.cpp
widgets/mainwindow.h
widgets/passwordeditorwidget.cpp
widgets/passwordeditorwidget.h
widgets/passwordgeneratorwidget.cpp
widgets/passwordgeneratorwidget.h
widgets/passwordviewerwidget.cpp
widgets/passwordviewerwidget.h
widgets/qpushbuttonfactory.h
widgets/qrcodepopup.cpp
widgets/qrcodepopup.h
widgets/setupwidget.cpp
widgets/setupwidget.h
widgets/usersdialog.cpp
widgets/usersdialog.h
widgets/welcomewidget.cpp
widgets/welcomewidget.h
zxcvbn/zxcvbn.c
zxcvbn/zxcvbn.h
)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-gpgpass.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-gpgpass.h)
+
kconfig_add_kcfg_files(gpgpass_internal GENERATE_MOC
config.kcfgc
rootfolderconfig.kcfgc
)
ki18n_wrap_ui(gpgpass_internal
conf/generalconfigurationpage.ui
conf/rootfoldersconfigurationpage.ui
conf/templateconfigurationpage.ui
widgets/passwordeditorwidget.ui
widgets/passwordgeneratorwidget.ui
widgets/mainwindow.ui
widgets/usersdialog.ui
widgets/userswidget.ui
)
target_link_libraries(gpgpass_internal
Qt::Widgets
KF${QT_MAJOR_VERSION}::CoreAddons
KF${QT_MAJOR_VERSION}::ConfigCore
KF${QT_MAJOR_VERSION}::ConfigGui
KF${QT_MAJOR_VERSION}::Prison
KF${QT_MAJOR_VERSION}::IconThemes
KF${QT_MAJOR_VERSION}::I18n
KF${QT_MAJOR_VERSION}::WidgetsAddons
KF${QT_MAJOR_VERSION}::ItemModels
KF${QT_MAJOR_VERSION}::ItemViews
KF${QT_MAJOR_VERSION}::KIOWidgets
KF${QT_MAJOR_VERSION}::XmlGui
KPim${QT_MAJOR_VERSION}::Libkleo
)
+if (${HAVE_QDBUS})
+ target_link_libraries(gpgpass_internal KF${QT_MAJOR_VERSION}::DBusAddons)
+endif ()
+
if (QT_MAJOR_VERSION STREQUAL "6")
target_link_libraries(gpgpass_internal QGpgmeQt6 LibGpgError::LibGpgError KF6::ColorScheme)
target_sources(gpgpass_internal PRIVATE
job/openpgpcertificatecreationjob.cpp
job/openpgpcertificatecreationjob.h
)
else()
target_link_libraries(gpgpass_internal QGpgme KF5::ConfigWidgets)
endif()
diff --git a/src/config-gpgpass.h.in b/src/config-gpgpass.h.in
new file mode 100644
index 0000000..fe9569e
--- /dev/null
+++ b/src/config-gpgpass.h.in
@@ -0,0 +1,5 @@
+// SPDX-FileCopyrightText: 2025 g10 Code GmbH
+// SPDX-FileContributor: Tobias Fella <tobias.fella@gnupg.com>
+// SPDX-License-Identifier: LGPL-2.0-or-later
+
+#cmakedefine01 HAVE_QDBUS
diff --git a/src/kuniqueservice.cpp b/src/kuniqueservice.cpp
new file mode 100644
index 0000000..1c4a5e3
--- /dev/null
+++ b/src/kuniqueservice.cpp
@@ -0,0 +1,19 @@
+/*
+ SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
+ SPDX-FileContributor: Intevation GmbH
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#include <config-gpgpass.h>
+
+// Includes the real implementation
+
+#if !HAVE_QDBUS && defined(_WIN32)
+#include "kuniqueservice_win.cpp"
+#elif HAVE_QDBUS
+#include "kuniqueservice_dbus.cpp"
+#else
+#error "Uniqueservice is only implemented for DBus and Windows."
+#endif
+
+#include "moc_kuniqueservice.cpp"
diff --git a/src/kuniqueservice.h b/src/kuniqueservice.h
new file mode 100644
index 0000000..4132d7c
--- /dev/null
+++ b/src/kuniqueservice.h
@@ -0,0 +1,65 @@
+/*
+ SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
+ SPDX-FileContributor: Intevation GmbH
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#pragma once
+
+#include <QObject>
+#include <QString>
+#include <QStringList>
+
+/**
+ * This class can be used to create a unique service and redirect calls
+ * to this service similarly to KDBusService(KDBusService::Unique).
+ * @code
+ * YourApplication app(argc, argv);
+ *
+ * KUniqueService service;
+ * QObject::connect(&service, &KUniqueService::activateRequested,
+ * &app, &YourApplication::slotActivateRequested);
+ * QObject::connect(&app, &YourApplication::setExitValue,
+ * &service, [&service](int i) {
+ * service.setExitValue(i);
+ * });
+ * @endcode
+ * This will redirect calls to running instances over the
+ * the slotActivateRequested. When you set the exit
+ * value the calling process will afterwards exit with the
+ * code provided.
+ * If you do not set the exit value the application will not
+ * be terminated.
+ * @author Andre Heinecke (aheinecke@intevation.org)
+ */
+class KUniqueService : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor
+ */
+ KUniqueService();
+ ~KUniqueService() override;
+
+public Q_SLOTS:
+ /**
+ * Set the exit @p code the second app should use to terminate.
+ * If unset it exits with 0.
+ * @param code The exit code.
+ */
+ void setExitValue(int code);
+
+Q_SIGNALS:
+ void activateRequested(const QStringList &arguments, const QString &workingDirectory);
+
+private:
+ void emitActivateRequested(const QStringList &arguments, const QString &workingDirectory)
+ {
+ Q_EMIT activateRequested(arguments, workingDirectory);
+ }
+ class KUniqueServicePrivate;
+ Q_DECLARE_PRIVATE(KUniqueService)
+ KUniqueServicePrivate *d_ptr;
+};
diff --git a/src/kuniqueservice_dbus.cpp b/src/kuniqueservice_dbus.cpp
new file mode 100644
index 0000000..2b027ab
--- /dev/null
+++ b/src/kuniqueservice_dbus.cpp
@@ -0,0 +1,45 @@
+/*
+ SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
+ SPDX-FileContributor: Intevation GmbH
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "kuniqueservice.h"
+#include <KDBusService>
+
+class KUniqueService::KUniqueServicePrivate
+{
+ Q_DISABLE_COPY(KUniqueServicePrivate)
+
+public:
+ KUniqueServicePrivate(KUniqueService *q)
+ : mService(KDBusService::Unique)
+ {
+ QObject::connect(&mService, &KDBusService::activateRequested, q, &KUniqueService::activateRequested);
+ }
+
+ void setExitValue(int code)
+ {
+ mService.setExitValue(code);
+ }
+
+private:
+ KDBusService mService;
+};
+
+KUniqueService::KUniqueService()
+ : d_ptr(new KUniqueServicePrivate(this))
+{
+}
+
+KUniqueService::~KUniqueService()
+{
+ delete d_ptr;
+}
+
+void KUniqueService::setExitValue(int code)
+{
+ Q_D(KUniqueService);
+ d->setExitValue(code);
+}
diff --git a/src/kuniqueservice_win.cpp b/src/kuniqueservice_win.cpp
new file mode 100644
index 0000000..e935b79
--- /dev/null
+++ b/src/kuniqueservice_win.cpp
@@ -0,0 +1,196 @@
+/*
+ SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
+ SPDX-FileContributor: Intevation GmbH
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "kuniqueservice.h"
+
+#include <QCoreApplication>
+#include <QDataStream>
+#include <QDir>
+
+#include <KLocalizedString>
+#include <KMessageBox>
+
+#include <windows.h>
+
+#define MY_DATA_TYPE 12
+
+class KUniqueService::KUniqueServicePrivate
+{
+ Q_DECLARE_PUBLIC(KUniqueService)
+ Q_DISABLE_COPY(KUniqueServicePrivate)
+
+private:
+ KUniqueService *q_ptr;
+ HWND mResponder;
+ HANDLE mResponderProc;
+
+ const QString getWindowName() const
+ {
+ return QCoreApplication::applicationName() + QStringLiteral("Responder");
+ }
+
+ HWND getForeignResponder() const
+ {
+ const QString qWndName = getWindowName();
+ wchar_t *wndName = (wchar_t *)qWndName.utf16();
+ HWND ret = FindWindow(wndName, wndName);
+ qDebug() << "Responder handle:" << ret;
+ return ret;
+ }
+
+ void createResponder()
+ {
+ WNDCLASS windowClass;
+ const QString qWndName = getWindowName();
+ wchar_t *wndName = (wchar_t *)qWndName.utf16();
+ windowClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
+ windowClass.lpfnWndProc = windowProc;
+ windowClass.hInstance = (HINSTANCE)GetModuleHandle(NULL);
+ windowClass.lpszClassName = wndName;
+ windowClass.hIcon = nullptr;
+ windowClass.hCursor = nullptr;
+ windowClass.hbrBackground = nullptr;
+ windowClass.lpszMenuName = nullptr;
+ windowClass.cbClsExtra = 0;
+ windowClass.cbWndExtra = 0;
+ RegisterClass(&windowClass);
+ mResponder = CreateWindow(wndName, wndName, 0, 0, 0, 10, 10, nullptr, nullptr, (HINSTANCE)GetModuleHandle(NULL), nullptr);
+ qDebug() << "Created responder: " << qWndName << " with handle: " << mResponder;
+ }
+
+ void handleRequest(const COPYDATASTRUCT *cds)
+ {
+ Q_Q(KUniqueService);
+ if (cds->dwData != MY_DATA_TYPE) {
+ qDebug() << "Responder called with invalid data type:" << cds->dwData;
+ return;
+ }
+ if (mResponderProc) {
+ qDebug() << "Already serving. Terminating process: " << mResponderProc;
+ setExitValue(42);
+ }
+ const QByteArray serialized(static_cast<const char *>(cds->lpData), cds->cbData);
+ QDataStream ds(serialized);
+ intptr_t curProc;
+ ds >> curProc;
+ mResponderProc = reinterpret_cast<HANDLE>(curProc);
+ QString workDir;
+ ds >> workDir;
+ QStringList args;
+ ds >> args;
+ qDebug() << "Process handle: " << mResponderProc << " requests activate with args " << args;
+ q->emitActivateRequested(args, workDir);
+ return;
+ }
+
+ KUniqueServicePrivate(KUniqueService *q)
+ : q_ptr(q)
+ , mResponder(nullptr)
+ , mResponderProc(nullptr)
+ {
+ HWND responder = getForeignResponder();
+ if (!responder) {
+ // We are the responder
+ createResponder();
+ return;
+ }
+ // We are the client
+ QByteArray serialized;
+ QDataStream ds(&serialized, QIODevice::WriteOnly);
+ DWORD responderId = 0;
+ GetWindowThreadProcessId(responder, &responderId);
+ if (!responderId) {
+ qDebug() << "No id of responder window";
+ return;
+ }
+
+ // To allow the other process to terminate the process
+ // needs a handle to us with the required access.
+ int err = 0;
+ HANDLE responderHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, responderId);
+ if (!responderHandle) {
+ qDebug() << "Open process returned NULL. Err: " << GetLastError();
+ err = 1;
+ } else if (!DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), responderHandle, &mResponderProc, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+ qDebug() << "Duplicate Handle failed. Err: " << GetLastError();
+ err = 2;
+ }
+ if (err) {
+ KMessageBox::error(nullptr,
+ xi18nc("@info",
+ "<para><application>Gpgpass</application> seems to be running for you already, but with different privileges.</para>"
+ "<para>This usually happens if <application>Gpgpass</application> is accidentally run as Administrator.</para>"
+ "<para>Please right click the tray icon of <application>Gpgpass</application> and select 'quit' to try again.</para>"),
+ xi18nc("@title", "<application>Gpgpass</application> failed to start"));
+ exit(err);
+ }
+ CloseHandle(responderHandle);
+
+ ds << reinterpret_cast<intptr_t>(mResponderProc) << QDir::currentPath() << QCoreApplication::arguments();
+ COPYDATASTRUCT cds;
+ cds.dwData = MY_DATA_TYPE;
+ cds.cbData = serialized.size();
+ cds.lpData = serialized.data();
+
+ qDebug() << "Sending message to existing Window.";
+ SendMessage(responder, WM_COPYDATA, 0, (LPARAM)&cds);
+ // Usually we should be terminated while sending the message.
+ qDebug() << "Send message returned.";
+ }
+
+ static KUniqueServicePrivate *instance(KUniqueService *q)
+ {
+ static KUniqueServicePrivate *self;
+ if (self) {
+ return self;
+ }
+
+ self = new KUniqueServicePrivate(q);
+ return self;
+ }
+
+ static LRESULT CALLBACK windowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+ {
+ if (message == WM_COPYDATA) {
+ const COPYDATASTRUCT *cds = (COPYDATASTRUCT *)lParam;
+ // windowProc must be static so the singleton pattern although
+ // it doesn't make much sense in here.
+ instance(nullptr)->handleRequest(cds);
+ return 0;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+
+ ~KUniqueServicePrivate()
+ {
+ if (mResponder) {
+ DestroyWindow(mResponder);
+ }
+ }
+
+ void setExitValue(int code)
+ {
+ TerminateProcess(mResponderProc, (unsigned int)code);
+ mResponderProc = nullptr;
+ }
+};
+
+KUniqueService::KUniqueService()
+ : d_ptr(KUniqueServicePrivate::instance(this))
+{
+}
+
+KUniqueService::~KUniqueService()
+{
+ delete d_ptr;
+}
+
+void KUniqueService::setExitValue(int code)
+{
+ Q_D(KUniqueService);
+ d->setExitValue(code);
+}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Dec 28, 10:32 PM (4 h, 39 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
d9/37/ea2cc8d0265eff1bdbd963e34b49

Event Timeline