SYNERGY3-17 Stop on login screen (#7143)
* SYNERGY3-17 Stop on login screen * SYNERGY3-17 Fix code smells * SYNERGY3-17 Update ChangeLog
This commit is contained in:
parent
bf102d4601
commit
d3d7c36f58
12 changed files with 236 additions and 23 deletions
|
|
@ -1,3 +1,9 @@
|
||||||
|
v1.14.4-snapshot
|
||||||
|
===========
|
||||||
|
Enhancements:
|
||||||
|
- #7143 Add ability to stop synergy on the login screen
|
||||||
|
===========
|
||||||
|
|
||||||
v1.14.3-snapshot
|
v1.14.3-snapshot
|
||||||
===========
|
===========
|
||||||
Bug fixes:
|
Bug fixes:
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ cmake_minimum_required (VERSION 3.4)
|
||||||
|
|
||||||
set (SYNERGY_VERSION_MAJOR 1)
|
set (SYNERGY_VERSION_MAJOR 1)
|
||||||
set (SYNERGY_VERSION_MINOR 14)
|
set (SYNERGY_VERSION_MINOR 14)
|
||||||
set (SYNERGY_VERSION_PATCH 3)
|
set (SYNERGY_VERSION_PATCH 4)
|
||||||
set (SYNERGY_VERSION_BUILD 1)
|
set (SYNERGY_VERSION_BUILD 1)
|
||||||
set (SYNERGY_VERSION_STAGE "snapshot")
|
set (SYNERGY_VERSION_STAGE "snapshot")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include "ipc/Ipc.h"
|
#include "ipc/Ipc.h"
|
||||||
|
|
||||||
const char* kIpcMsgHello = "IHEL%1i";
|
const char* kIpcMsgHello = "IHEL%1i";
|
||||||
const char* kIpcMsgLogLine = "ILOG%s";
|
const char* kIpcMsgLogLine = "ILOG%s";
|
||||||
const char* kIpcMsgCommand = "ICMD%s%1i";
|
const char* kIpcMsgCommand = "ICMD%s%1i";
|
||||||
const char* kIpcMsgShutdown = "ISDN";
|
const char* kIpcMsgShutdown = "ISDN";
|
||||||
|
const char* kIpcMsgSetting = "SSET%s%s";
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ enum EIpcMessage {
|
||||||
kIpcLogLine,
|
kIpcLogLine,
|
||||||
kIpcCommand,
|
kIpcCommand,
|
||||||
kIpcShutdown,
|
kIpcShutdown,
|
||||||
|
kIpcSetting
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EIpcClientType {
|
enum EIpcClientType {
|
||||||
|
|
@ -50,3 +51,8 @@ extern const char* kIpcMsgCommand;
|
||||||
// shutdown: daemon -> node
|
// shutdown: daemon -> node
|
||||||
// the daemon tells synergys/c to shut down gracefully.
|
// the daemon tells synergys/c to shut down gracefully.
|
||||||
extern const char* kIpcMsgShutdown;
|
extern const char* kIpcMsgShutdown;
|
||||||
|
|
||||||
|
// set setting: gui -> daemon
|
||||||
|
// $1 = setting name
|
||||||
|
// $2 = setting value
|
||||||
|
extern const char* kIpcMsgSetting;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "ipc/Ipc.h"
|
#include "ipc/Ipc.h"
|
||||||
#include "ipc/IpcMessage.h"
|
#include "ipc/IpcMessage.h"
|
||||||
|
#include "ipc/IpcSettingMessage.h"
|
||||||
#include "synergy/ProtocolUtil.h"
|
#include "synergy/ProtocolUtil.h"
|
||||||
#include "io/IStream.h"
|
#include "io/IStream.h"
|
||||||
#include "arch/Arch.h"
|
#include "arch/Arch.h"
|
||||||
|
|
@ -117,6 +118,9 @@ IpcClientProxy::handleData(const Event&, void*)
|
||||||
else if (memcmp(code, kIpcMsgCommand, 4) == 0) {
|
else if (memcmp(code, kIpcMsgCommand, 4) == 0) {
|
||||||
m = parseCommand();
|
m = parseCommand();
|
||||||
}
|
}
|
||||||
|
else if (memcmp(code, kIpcMsgSetting, 4) == 0) {
|
||||||
|
m = parseSetting();
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
LOG((CLOG_ERR "invalid ipc message"));
|
LOG((CLOG_ERR "invalid ipc message"));
|
||||||
disconnect();
|
disconnect();
|
||||||
|
|
@ -184,6 +188,18 @@ IpcClientProxy::parseCommand()
|
||||||
return new IpcCommandMessage(command, elevate != 0);
|
return new IpcCommandMessage(command, elevate != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IpcSettingMessage*
|
||||||
|
IpcClientProxy::parseSetting() const
|
||||||
|
{
|
||||||
|
String name;
|
||||||
|
String value;
|
||||||
|
|
||||||
|
ProtocolUtil::readf(&m_stream, kIpcMsgSetting + 4, &name, &value);
|
||||||
|
|
||||||
|
// must be deleted by event handler.
|
||||||
|
return new IpcSettingMessage(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
IpcClientProxy::disconnect()
|
IpcClientProxy::disconnect()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
namespace synergy { class IStream; }
|
namespace synergy { class IStream; }
|
||||||
class IpcMessage;
|
class IpcMessage;
|
||||||
class IpcCommandMessage;
|
class IpcCommandMessage;
|
||||||
|
class IpcSettingMessage;
|
||||||
class IpcHelloMessage;
|
class IpcHelloMessage;
|
||||||
class IEventQueue;
|
class IEventQueue;
|
||||||
|
|
||||||
|
|
@ -47,7 +48,8 @@ private:
|
||||||
void handleDisconnect(const Event&, void*);
|
void handleDisconnect(const Event&, void*);
|
||||||
void handleWriteError(const Event&, void*);
|
void handleWriteError(const Event&, void*);
|
||||||
IpcHelloMessage* parseHello();
|
IpcHelloMessage* parseHello();
|
||||||
IpcCommandMessage* parseCommand();
|
IpcCommandMessage* parseCommand();
|
||||||
|
IpcSettingMessage* parseSetting() const;
|
||||||
void disconnect();
|
void disconnect();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
38
src/lib/ipc/IpcSettingMessage.cpp
Normal file
38
src/lib/ipc/IpcSettingMessage.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2012-2016 Symless Ltd.
|
||||||
|
* Copyright (C) 2012 Nick Bolton
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IpcSettingMessage.h"
|
||||||
|
|
||||||
|
IpcSettingMessage::IpcSettingMessage(const std::string& name, const std::string& value) :
|
||||||
|
IpcMessage(kIpcSetting),
|
||||||
|
m_name(name),
|
||||||
|
m_value(value)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& IpcSettingMessage::getName() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& IpcSettingMessage::getValue() const
|
||||||
|
{
|
||||||
|
return m_value;
|
||||||
|
}
|
||||||
|
|
||||||
50
src/lib/ipc/IpcSettingMessage.h
Normal file
50
src/lib/ipc/IpcSettingMessage.h
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2012-2016 Symless Ltd.
|
||||||
|
* Copyright (C) 2012 Nick Bolton
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "IpcMessage.h"
|
||||||
|
|
||||||
|
class IpcSettingMessage : public IpcMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//!
|
||||||
|
//! \brief IpcSettingMessage constructor
|
||||||
|
//! \param name - setting name
|
||||||
|
//! \param value - setting value
|
||||||
|
//!
|
||||||
|
IpcSettingMessage(const std::string& name, const std::string& value);
|
||||||
|
|
||||||
|
//!
|
||||||
|
//! \brief getName is a getter for the setting name
|
||||||
|
//! \return setting name
|
||||||
|
//!
|
||||||
|
const std::string& getName() const;
|
||||||
|
|
||||||
|
//!
|
||||||
|
//! \brief getValue is a getter for the setting value
|
||||||
|
//! \return setting value
|
||||||
|
//!
|
||||||
|
const std::string& getValue() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -39,6 +39,42 @@
|
||||||
|
|
||||||
#define CURRENT_PROCESS_ID 0
|
#define CURRENT_PROCESS_ID 0
|
||||||
#define MAXIMUM_WAIT_TIME 3
|
#define MAXIMUM_WAIT_TIME 3
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string
|
||||||
|
trimDesktopName(const std::string& nameFromTraces)
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
for (const auto& symbol : nameFromTraces) {
|
||||||
|
if (std::isalpha(symbol)) {
|
||||||
|
name.push_back(symbol);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isDesktopRunnable(const std::string& desktopName)
|
||||||
|
{
|
||||||
|
const std::string winlogon = "Winlogon";
|
||||||
|
bool isNotLoginScreen = std::strncmp(desktopName.c_str(),
|
||||||
|
winlogon.c_str(),
|
||||||
|
winlogon.length());
|
||||||
|
|
||||||
|
const auto setting = ARCH->setting("runOnLoginScreen");
|
||||||
|
bool runOnLoginScreen = (setting.empty() || setting == "true");
|
||||||
|
|
||||||
|
return (runOnLoginScreen || isNotLoginScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kOutputBufferSize = 4096
|
kOutputBufferSize = 4096
|
||||||
};
|
};
|
||||||
|
|
@ -315,17 +351,22 @@ MSWindowsWatchdog::startProcess()
|
||||||
|
|
||||||
getActiveDesktop(&sa);
|
getActiveDesktop(&sa);
|
||||||
|
|
||||||
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
|
if (!isDesktopRunnable(m_activeDesktop)) {
|
||||||
HANDLE userToken = getUserToken(&sa);
|
LOG((CLOG_INFO, "Starting on the login screen is disabled!"));
|
||||||
m_elevateProcess = m_autoElevated ? m_autoElevated : m_elevateProcess;
|
return;
|
||||||
m_autoElevated = false;
|
}
|
||||||
|
|
||||||
// patch by Jack Zhou and Henry Tung
|
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
|
||||||
// set UIAccess to fix Windows 8 GUI interaction
|
HANDLE userToken = getUserToken(&sa);
|
||||||
DWORD uiAccess = 1;
|
m_elevateProcess = m_autoElevated ? m_autoElevated : m_elevateProcess;
|
||||||
SetTokenInformation(userToken, TokenUIAccess, &uiAccess, sizeof(DWORD));
|
m_autoElevated = false;
|
||||||
|
|
||||||
createRet = startProcessAsUser(m_command, userToken, &sa);
|
// patch by Jack Zhou and Henry Tung
|
||||||
|
// set UIAccess to fix Windows 8 GUI interaction
|
||||||
|
DWORD uiAccess = 1;
|
||||||
|
SetTokenInformation(userToken, TokenUIAccess, &uiAccess, sizeof(DWORD));
|
||||||
|
|
||||||
|
createRet = startProcessAsUser(m_command, userToken, &sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!createRet) {
|
if (!createRet) {
|
||||||
|
|
@ -636,7 +677,7 @@ MSWindowsWatchdog::getActiveDesktop(LPSECURITY_ATTRIBUTES security)
|
||||||
ARCH->unlockMutex(m_mutex);
|
ARCH->unlockMutex(m_mutex);
|
||||||
closeProcessHandles(pid);
|
closeProcessHandles(pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MSWindowsWatchdog::testOutput(String buffer)
|
MSWindowsWatchdog::testOutput(String buffer)
|
||||||
|
|
@ -645,11 +686,11 @@ MSWindowsWatchdog::testOutput(String buffer)
|
||||||
size_t i = buffer.find(g_activeDesktop);
|
size_t i = buffer.find(g_activeDesktop);
|
||||||
if (i != String::npos) {
|
if (i != String::npos) {
|
||||||
size_t s = sizeof(g_activeDesktop);
|
size_t s = sizeof(g_activeDesktop);
|
||||||
String defaultDesktop("Default");
|
std::string defaultScreen = "Default";
|
||||||
String sub = buffer.substr(i + s - 1, defaultDesktop.size());
|
m_activeDesktop = trimDesktopName(buffer.substr(i + s - 1));
|
||||||
if (sub != defaultDesktop) {
|
m_autoElevated = std::strncmp(m_activeDesktop.c_str(),
|
||||||
m_autoElevated = true;
|
defaultScreen.c_str(),
|
||||||
}
|
defaultScreen.length());
|
||||||
|
|
||||||
ARCH->lockMutex(m_mutex);
|
ARCH->lockMutex(m_mutex);
|
||||||
m_ready = true;
|
m_ready = true;
|
||||||
|
|
|
||||||
|
|
@ -96,12 +96,13 @@ private:
|
||||||
ArchMutex m_mutex;
|
ArchMutex m_mutex;
|
||||||
ArchCond m_condVar;
|
ArchCond m_condVar;
|
||||||
bool m_ready;
|
bool m_ready;
|
||||||
bool m_foreground;
|
bool m_foreground;
|
||||||
|
std::string m_activeDesktop;
|
||||||
|
|
||||||
/// @brief Save the info of all process made
|
/// @brief Save the info of all process made
|
||||||
/// We will use this to track all processes we make and
|
/// We will use this to track all processes we make and
|
||||||
/// kill off handels and children that we no longer need
|
/// kill off handels and children that we no longer need
|
||||||
std::map<unsigned long, PROCESS_INFORMATION> m_children;
|
std::map<unsigned long, PROCESS_INFORMATION> m_children;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Relauncher error
|
//! Relauncher error
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "synergy/ClientArgs.h"
|
#include "synergy/ClientArgs.h"
|
||||||
#include "ipc/IpcClientProxy.h"
|
#include "ipc/IpcClientProxy.h"
|
||||||
#include "ipc/IpcMessage.h"
|
#include "ipc/IpcMessage.h"
|
||||||
|
#include "ipc/IpcSettingMessage.h"
|
||||||
#include "ipc/IpcLogOutputter.h"
|
#include "ipc/IpcLogOutputter.h"
|
||||||
#include "net/SocketMultiplexer.h"
|
#include "net/SocketMultiplexer.h"
|
||||||
#include "arch/XArch.h"
|
#include "arch/XArch.h"
|
||||||
|
|
@ -58,6 +59,21 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void
|
||||||
|
updateSetting(const IpcMessage& message)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
auto setting = static_cast<const IpcSettingMessage&>(message);
|
||||||
|
ARCH->setting(setting.getName(), setting.getValue());
|
||||||
|
}
|
||||||
|
catch (const XArch& e) {
|
||||||
|
LOG((CLOG_ERR "failed to save setting: %s", e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}//namespace
|
||||||
|
|
||||||
DaemonApp* DaemonApp::s_instance = NULL;
|
DaemonApp* DaemonApp::s_instance = NULL;
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -362,7 +378,7 @@ DaemonApp::handleIpcMessage(const Event& e, void*)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case kIpcHello:
|
case kIpcHello: {
|
||||||
IpcHelloMessage* hm = static_cast<IpcHelloMessage*>(m);
|
IpcHelloMessage* hm = static_cast<IpcHelloMessage*>(m);
|
||||||
String type;
|
String type;
|
||||||
switch (hm->clientType()) {
|
switch (hm->clientType()) {
|
||||||
|
|
@ -380,5 +396,10 @@ DaemonApp::handleIpcMessage(const Event& e, void*)
|
||||||
|
|
||||||
m_ipcLogOutputter->notifyBuffer();
|
m_ipcLogOutputter->notifyBuffer();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kIpcSetting:
|
||||||
|
updateSetting(*m);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
src/test/unittests/ipc/IpcSettingMessageTests.cpp
Normal file
31
src/test/unittests/ipc/IpcSettingMessageTests.cpp
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2015-2022 Symless Ltd.
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TEST_ENV
|
||||||
|
|
||||||
|
#include "ipc/IpcSettingMessage.h"
|
||||||
|
#include "test/global/gtest.h"
|
||||||
|
|
||||||
|
TEST(IpcSettingMessage, testIpcSettingMessage) {
|
||||||
|
const std::string expected_name = "test";
|
||||||
|
const std::string expected_value = "test_value";
|
||||||
|
|
||||||
|
IpcSettingMessage message("test", "test_value");
|
||||||
|
|
||||||
|
EXPECT_EQ(expected_name, message.getName());
|
||||||
|
EXPECT_EQ(expected_value, message.getValue());
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue