Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34307301
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
22 KB
Subscribers
None
View Options
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
Details
Attached
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
Attached To
rGPGPASS GnuPG Password Manager
Event Timeline
Log In to Comment