normalised line endings - replaced \r\n with \n

This commit is contained in:
Nick Bolton
2011-01-15 02:20:14 +00:00
parent 77200d5779
commit f4d937532e
32 changed files with 4129 additions and 4129 deletions

View File

@@ -189,12 +189,12 @@ public:
// IArchAppUtil overrides
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
virtual void adoptApp(CApp* app);
virtual CApp& app() const;
virtual CApp& app() const;
virtual int run(int argc, char** argv);
virtual void beforeAppExit();
// expose util so we don't need to re-implement all the functions
IArchAppUtil& util() const { return *m_appUtil; }
IArchAppUtil& util() const { return *m_appUtil; }
IArchDaemon& daemon() const { return *m_daemon; }
private:

View File

@@ -1,60 +1,60 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtil.h"
#include "CApp.h"
CArchAppUtil* CArchAppUtil::s_instance = nullptr;
CArchAppUtil::CArchAppUtil() :
m_app(nullptr)
{
s_instance = this;
}
CArchAppUtil::~CArchAppUtil()
{
}
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtil.h"
#include "CApp.h"
bool
CArchAppUtil::parseArg(const int& argc, const char* const* argv, int& i)
{
// no common platform args (yet)
return false;
}
void
CArchAppUtil::adoptApp(CApp* app)
{
app->m_bye = &exitAppStatic;
m_app = app;
}
CApp&
CArchAppUtil::app() const
{
assert(m_app != nullptr);
return *m_app;
}
CArchAppUtil&
CArchAppUtil::instance()
{
assert(s_instance != nullptr);
return *s_instance;
}
CArchAppUtil* CArchAppUtil::s_instance = nullptr;
CArchAppUtil::CArchAppUtil() :
m_app(nullptr)
{
s_instance = this;
}
CArchAppUtil::~CArchAppUtil()
{
}
bool
CArchAppUtil::parseArg(const int& argc, const char* const* argv, int& i)
{
// no common platform args (yet)
return false;
}
void
CArchAppUtil::adoptApp(CApp* app)
{
app->m_bye = &exitAppStatic;
m_app = app;
}
CApp&
CArchAppUtil::app() const
{
assert(m_app != nullptr);
return *m_app;
}
CArchAppUtil&
CArchAppUtil::instance()
{
assert(s_instance != nullptr);
return *s_instance;
}

View File

@@ -1,41 +1,41 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "IArchAppUtil.h"
#include "XSynergy.h"
class CArchAppUtil : public IArchAppUtil {
public:
CArchAppUtil();
virtual ~CArchAppUtil();
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
virtual void adoptApp(CApp* app);
CApp& app() const;
virtual void exitApp(int code) { throw XExitApp(code); }
static CArchAppUtil& instance();
static void exitAppStatic(int code) { instance().exitApp(code); }
virtual void beforeAppExit() {}
private:
CApp* m_app;
static CArchAppUtil* s_instance;
};
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "IArchAppUtil.h"
#include "XSynergy.h"
class CArchAppUtil : public IArchAppUtil {
public:
CArchAppUtil();
virtual ~CArchAppUtil();
virtual bool parseArg(const int& argc, const char* const* argv, int& i);
virtual void adoptApp(CApp* app);
CApp& app() const;
virtual void exitApp(int code) { throw XExitApp(code); }
static CArchAppUtil& instance();
static void exitAppStatic(int code) { instance().exitApp(code); }
virtual void beforeAppExit() {}
private:
CApp* m_app;
static CArchAppUtil* s_instance;
};

View File

@@ -1,57 +1,57 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtilUnix.h"
CArchAppUtilUnix::CArchAppUtilUnix()
{
}
CArchAppUtilUnix::~CArchAppUtilUnix()
{
}
bool
CArchAppUtilUnix::parseArg(const int& argc, const char* const* argv, int& i)
{
#if WINAPI_XWINDOWS
if (app().isArg(i, argc, argv, "-display", "--display", 1)) {
// use alternative display
app().argsBase().m_display = argv[++i];
}
else {
// option not supported here
return false;
}
return true;
#else
// no options for carbon
return false;
#endif
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtilUnix.h"
CArchAppUtilUnix::CArchAppUtilUnix()
{
}
CArchAppUtilUnix::~CArchAppUtilUnix()
{
}
bool
CArchAppUtilUnix::parseArg(const int& argc, const char* const* argv, int& i)
{
#if WINAPI_XWINDOWS
if (app().isArg(i, argc, argv, "-display", "--display", 1)) {
// use alternative display
app().argsBase().m_display = argv[++i];
}
else {
// option not supported here
return false;
}
return true;
#else
// no options for carbon
return false;
#endif
}
int
standardStartupStatic(int argc, char** argv)
{
return CArchAppUtil::instance().app().standardStartup(argc, argv);
}
}
int
CArchAppUtilUnix::run(int argc, char** argv)

View File

@@ -1,33 +1,33 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtil.h"
#define ARCH_APPUTIL CArchAppUtilUnix
class CArchAppUtilUnix : public CArchAppUtil {
public:
CArchAppUtilUnix();
virtual ~CArchAppUtilUnix();
bool parseArg(const int& argc, const char* const* argv, int& i);
int run(int argc, char** argv);
void startNode();
};
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtil.h"
#define ARCH_APPUTIL CArchAppUtilUnix
class CArchAppUtilUnix : public CArchAppUtil {
public:
CArchAppUtilUnix();
virtual ~CArchAppUtilUnix();
bool parseArg(const int& argc, const char* const* argv, int& i);
int run(int argc, char** argv);
void startNode();
};

View File

@@ -1,338 +1,338 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtilWindows.h"
#include "Version.h"
#include "CLog.h"
#include "XArchWindows.h"
#include "CArchMiscWindows.h"
#include "CApp.h"
#include "LogOutputters.h"
#include "CMSWindowsScreen.h"
#include "XSynergy.h"
#include "IArchTaskBarReceiver.h"
#include "CMSWindowsRelauncher.h"
#include "CScreen.h"
#include <sstream>
#include <iostream>
#include <conio.h>
CArchAppUtilWindows::CArchAppUtilWindows() :
m_exitMode(kExitModeNormal)
{
if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)consoleHandler, TRUE) == FALSE)
{
throw XArchEvalWindows();
}
}
CArchAppUtilWindows::~CArchAppUtilWindows()
{
}
BOOL WINAPI CArchAppUtilWindows::consoleHandler(DWORD CEvent)
{
if (instance().app().m_taskBarReceiver)
{
// HACK: it would be nice to delete the s_taskBarReceiver object, but
// this is best done by the CApp destructor; however i don't feel like
// opening up that can of worms today... i need sleep.
instance().app().m_taskBarReceiver->cleanup();
}
ExitProcess(kExitTerminated);
return TRUE;
}
bool
CArchAppUtilWindows::parseArg(const int& argc, const char* const* argv, int& i)
{
if (app().isArg(i, argc, argv, NULL, "--service")) {
const char* action = argv[++i];
if (_stricmp(action, "install") == 0) {
installService();
}
else if (_stricmp(action, "uninstall") == 0) {
uninstallService();
}
else if (_stricmp(action, "start") == 0) {
startService();
}
else if (_stricmp(action, "stop") == 0) {
stopService();
}
else {
LOG((CLOG_ERR "unknown service action: %s", action));
app().m_bye(kExitArgs);
}
app().m_bye(kExitSuccess);
}
else if (app().isArg(i, argc, argv, NULL, "--debug-service-wait")) {
app().argsBase().m_debugServiceWait = true;
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtilWindows.h"
#include "Version.h"
#include "CLog.h"
#include "XArchWindows.h"
#include "CArchMiscWindows.h"
#include "CApp.h"
#include "LogOutputters.h"
#include "CMSWindowsScreen.h"
#include "XSynergy.h"
#include "IArchTaskBarReceiver.h"
#include "CMSWindowsRelauncher.h"
#include "CScreen.h"
#include <sstream>
#include <iostream>
#include <conio.h>
CArchAppUtilWindows::CArchAppUtilWindows() :
m_exitMode(kExitModeNormal)
{
if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)consoleHandler, TRUE) == FALSE)
{
throw XArchEvalWindows();
}
}
CArchAppUtilWindows::~CArchAppUtilWindows()
{
}
BOOL WINAPI CArchAppUtilWindows::consoleHandler(DWORD CEvent)
{
if (instance().app().m_taskBarReceiver)
{
// HACK: it would be nice to delete the s_taskBarReceiver object, but
// this is best done by the CApp destructor; however i don't feel like
// opening up that can of worms today... i need sleep.
instance().app().m_taskBarReceiver->cleanup();
}
ExitProcess(kExitTerminated);
return TRUE;
}
bool
CArchAppUtilWindows::parseArg(const int& argc, const char* const* argv, int& i)
{
if (app().isArg(i, argc, argv, NULL, "--service")) {
const char* action = argv[++i];
if (_stricmp(action, "install") == 0) {
installService();
}
else if (_stricmp(action, "uninstall") == 0) {
uninstallService();
}
else if (_stricmp(action, "start") == 0) {
startService();
}
else if (_stricmp(action, "stop") == 0) {
stopService();
}
else {
LOG((CLOG_ERR "unknown service action: %s", action));
app().m_bye(kExitArgs);
}
app().m_bye(kExitSuccess);
}
else if (app().isArg(i, argc, argv, NULL, "--debug-service-wait")) {
app().argsBase().m_debugServiceWait = true;
}
else if (app().isArg(i, argc, argv, NULL, "--relaunch")) {
app().argsBase().m_relaunchMode = true;
}
else if (app().isArg(i, argc, argv, NULL, "--exit-pause")) {
app().argsBase().m_pauseOnExit = true;
}
else if (app().isArg(i, argc, argv, NULL, "--no-tray")) {
app().argsBase().m_disableTray = true;
}
else {
// option not supported here
return false;
}
return true;
}
CString
CArchAppUtilWindows::getServiceArgs() const
{
std::stringstream argBuf;
for (int i = 1; i < __argc; i++) {
const char* arg = __argv[i];
// ignore service setup args
if (_stricmp(arg, "--service") == 0) {
// ignore and skip the next arg also (service action)
i++;
}
else {
if (strchr(arg, ' ') != NULL) {
// surround argument with quotes if it contains a space
argBuf << " \"" << arg << "\"";
} else {
argBuf << " " << arg;
}
}
}
return argBuf.str();
}
void
CArchAppUtilWindows::installService()
{
CString args = getServiceArgs();
// get the path of this program
char thisPath[MAX_PATH];
GetModuleFileName(CArchMiscWindows::instanceWin32(), thisPath, MAX_PATH);
ARCH->installDaemon(
app().daemonName(), app().daemonInfo(),
thisPath, args.c_str(), NULL, true);
LOG((CLOG_INFO "service '%s' installed with args: %s",
app().daemonName(), args != "" ? args.c_str() : "none" ));
}
void
CArchAppUtilWindows::uninstallService()
{
ARCH->uninstallDaemon(app().daemonName(), true);
LOG((CLOG_INFO "service '%s' uninstalled", app().daemonName()));
}
void
CArchAppUtilWindows::startService()
{
// open service manager
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
if (mgr == NULL) {
throw XArchDaemonFailed(new XArchEvalWindows());
}
// open the service
SC_HANDLE service = OpenService(
mgr, app().daemonName(), SERVICE_START);
if (service == NULL) {
CloseServiceHandle(mgr);
throw XArchDaemonFailed(new XArchEvalWindows());
}
// start the service
if (StartService(service, 0, NULL)) {
LOG((CLOG_INFO "service '%s' started", app().daemonName()));
}
else {
throw XArchDaemonFailed(new XArchEvalWindows());
}
}
void
CArchAppUtilWindows::stopService()
{
// open service manager
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
if (mgr == NULL) {
throw XArchDaemonFailed(new XArchEvalWindows());
}
// open the service
SC_HANDLE service = OpenService(
mgr, app().daemonName(),
SERVICE_STOP | SERVICE_QUERY_STATUS);
if (service == NULL) {
CloseServiceHandle(mgr);
throw XArchDaemonFailed(new XArchEvalWindows());
}
// ask the service to stop, asynchronously
SERVICE_STATUS ss;
if (!ControlService(service, SERVICE_CONTROL_STOP, &ss)) {
DWORD dwErrCode = GetLastError();
if (dwErrCode != ERROR_SERVICE_NOT_ACTIVE) {
LOG((CLOG_ERR "cannot stop service '%s'", app().daemonName()));
throw XArchDaemonFailed(new XArchEvalWindows());
}
}
LOG((CLOG_INFO "service '%s' stopping asynchronously", app().daemonName()));
}
static
int
mainLoopStatic()
{
return CArchAppUtil::instance().app().mainLoop();
}
int
CArchAppUtilWindows::daemonNTMainLoop(int argc, const char** argv)
{
app().initApp(argc, argv);
debugServiceWait();
// NB: what the hell does this do?!
app().argsBase().m_backend = false;
return CArchMiscWindows::runDaemon(mainLoopStatic);
}
void
CArchAppUtilWindows::exitApp(int code)
{
switch (m_exitMode) {
case kExitModeDaemon:
CArchMiscWindows::daemonFailed(code);
break;
default:
throw XExitApp(code);
}
}
int daemonNTMainLoopStatic(int argc, const char** argv)
{
return CArchAppUtilWindows::instance().daemonNTMainLoop(argc, argv);
}
int
CArchAppUtilWindows::daemonNTStartup(int, char**)
{
CSystemLogger sysLogger(app().daemonName(), false);
m_exitMode = kExitModeDaemon;
return ARCH->daemonize(app().daemonName(), daemonNTMainLoopStatic);
}
static
int
daemonNTStartupStatic(int argc, char** argv)
{
return CArchAppUtilWindows::instance().daemonNTStartup(argc, argv);
}
static
int
foregroundStartupStatic(int argc, char** argv)
{
return CArchAppUtil::instance().app().foregroundStartup(argc, argv);
}
void
CArchAppUtilWindows::beforeAppExit()
{
// this can be handy for debugging, since the application is launched in
// a new console window, and will normally close on exit (making it so
// that we can't see error messages).
if (app().argsBase().m_pauseOnExit) {
std::cout << std::endl << "Press any key to exit..." << std::endl;
int c = _getch();
}
}
int
CArchAppUtilWindows::run(int argc, char** argv)
{
// record window instance for tray icon, etc
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
CMSWindowsScreen::init(CArchMiscWindows::instanceWin32());
CThread::getCurrentThread().setPriority(-14);
StartupFunc startup;
if (CArchMiscWindows::wasLaunchedAsService()) {
startup = &daemonNTStartupStatic;
} else {
startup = &foregroundStartupStatic;
app().argsBase().m_daemon = false;
}
return app().runInner(argc, argv, NULL, startup);
}
CArchAppUtilWindows&
CArchAppUtilWindows::instance()
{
return (CArchAppUtilWindows&)CArchAppUtil::instance();
}
void
CArchAppUtilWindows::debugServiceWait()
{
if (app().argsBase().m_debugServiceWait)
{
while(true)
{
// this code is only executed when the process is launched via the
// windows service controller (and --debug-service-wait arg is
// used). to debug, set a breakpoint on this line so that
// execution is delayed until the debugger is attached.
ARCH->sleep(1);
LOG((CLOG_INFO "waiting for debugger to attach"));
}
}
}
void
CArchAppUtilWindows::startNode()
}
else if (app().isArg(i, argc, argv, NULL, "--exit-pause")) {
app().argsBase().m_pauseOnExit = true;
}
else if (app().isArg(i, argc, argv, NULL, "--no-tray")) {
app().argsBase().m_disableTray = true;
}
else {
// option not supported here
return false;
}
return true;
}
CString
CArchAppUtilWindows::getServiceArgs() const
{
std::stringstream argBuf;
for (int i = 1; i < __argc; i++) {
const char* arg = __argv[i];
// ignore service setup args
if (_stricmp(arg, "--service") == 0) {
// ignore and skip the next arg also (service action)
i++;
}
else {
if (strchr(arg, ' ') != NULL) {
// surround argument with quotes if it contains a space
argBuf << " \"" << arg << "\"";
} else {
argBuf << " " << arg;
}
}
}
return argBuf.str();
}
void
CArchAppUtilWindows::installService()
{
CString args = getServiceArgs();
// get the path of this program
char thisPath[MAX_PATH];
GetModuleFileName(CArchMiscWindows::instanceWin32(), thisPath, MAX_PATH);
ARCH->installDaemon(
app().daemonName(), app().daemonInfo(),
thisPath, args.c_str(), NULL, true);
LOG((CLOG_INFO "service '%s' installed with args: %s",
app().daemonName(), args != "" ? args.c_str() : "none" ));
}
void
CArchAppUtilWindows::uninstallService()
{
ARCH->uninstallDaemon(app().daemonName(), true);
LOG((CLOG_INFO "service '%s' uninstalled", app().daemonName()));
}
void
CArchAppUtilWindows::startService()
{
// open service manager
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
if (mgr == NULL) {
throw XArchDaemonFailed(new XArchEvalWindows());
}
// open the service
SC_HANDLE service = OpenService(
mgr, app().daemonName(), SERVICE_START);
if (service == NULL) {
CloseServiceHandle(mgr);
throw XArchDaemonFailed(new XArchEvalWindows());
}
// start the service
if (StartService(service, 0, NULL)) {
LOG((CLOG_INFO "service '%s' started", app().daemonName()));
}
else {
throw XArchDaemonFailed(new XArchEvalWindows());
}
}
void
CArchAppUtilWindows::stopService()
{
// open service manager
SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
if (mgr == NULL) {
throw XArchDaemonFailed(new XArchEvalWindows());
}
// open the service
SC_HANDLE service = OpenService(
mgr, app().daemonName(),
SERVICE_STOP | SERVICE_QUERY_STATUS);
if (service == NULL) {
CloseServiceHandle(mgr);
throw XArchDaemonFailed(new XArchEvalWindows());
}
// ask the service to stop, asynchronously
SERVICE_STATUS ss;
if (!ControlService(service, SERVICE_CONTROL_STOP, &ss)) {
DWORD dwErrCode = GetLastError();
if (dwErrCode != ERROR_SERVICE_NOT_ACTIVE) {
LOG((CLOG_ERR "cannot stop service '%s'", app().daemonName()));
throw XArchDaemonFailed(new XArchEvalWindows());
}
}
LOG((CLOG_INFO "service '%s' stopping asynchronously", app().daemonName()));
}
static
int
mainLoopStatic()
{
return CArchAppUtil::instance().app().mainLoop();
}
int
CArchAppUtilWindows::daemonNTMainLoop(int argc, const char** argv)
{
app().initApp(argc, argv);
debugServiceWait();
// NB: what the hell does this do?!
app().argsBase().m_backend = false;
return CArchMiscWindows::runDaemon(mainLoopStatic);
}
void
CArchAppUtilWindows::exitApp(int code)
{
switch (m_exitMode) {
case kExitModeDaemon:
CArchMiscWindows::daemonFailed(code);
break;
default:
throw XExitApp(code);
}
}
int daemonNTMainLoopStatic(int argc, const char** argv)
{
return CArchAppUtilWindows::instance().daemonNTMainLoop(argc, argv);
}
int
CArchAppUtilWindows::daemonNTStartup(int, char**)
{
CSystemLogger sysLogger(app().daemonName(), false);
m_exitMode = kExitModeDaemon;
return ARCH->daemonize(app().daemonName(), daemonNTMainLoopStatic);
}
static
int
daemonNTStartupStatic(int argc, char** argv)
{
return CArchAppUtilWindows::instance().daemonNTStartup(argc, argv);
}
static
int
foregroundStartupStatic(int argc, char** argv)
{
return CArchAppUtil::instance().app().foregroundStartup(argc, argv);
}
void
CArchAppUtilWindows::beforeAppExit()
{
// this can be handy for debugging, since the application is launched in
// a new console window, and will normally close on exit (making it so
// that we can't see error messages).
if (app().argsBase().m_pauseOnExit) {
std::cout << std::endl << "Press any key to exit..." << std::endl;
int c = _getch();
}
}
int
CArchAppUtilWindows::run(int argc, char** argv)
{
// record window instance for tray icon, etc
CArchMiscWindows::setInstanceWin32(GetModuleHandle(NULL));
CMSWindowsScreen::init(CArchMiscWindows::instanceWin32());
CThread::getCurrentThread().setPriority(-14);
StartupFunc startup;
if (CArchMiscWindows::wasLaunchedAsService()) {
startup = &daemonNTStartupStatic;
} else {
startup = &foregroundStartupStatic;
app().argsBase().m_daemon = false;
}
return app().runInner(argc, argv, NULL, startup);
}
CArchAppUtilWindows&
CArchAppUtilWindows::instance()
{
return (CArchAppUtilWindows&)CArchAppUtil::instance();
}
void
CArchAppUtilWindows::debugServiceWait()
{
if (app().argsBase().m_debugServiceWait)
{
while(true)
{
// this code is only executed when the process is launched via the
// windows service controller (and --debug-service-wait arg is
// used). to debug, set a breakpoint on this line so that
// execution is delayed until the debugger is attached.
ARCH->sleep(1);
LOG((CLOG_INFO "waiting for debugger to attach"));
}
}
}
void
CArchAppUtilWindows::startNode()
{
if (app().argsBase().m_relaunchMode) {
@@ -346,5 +346,5 @@ CArchAppUtilWindows::startNode()
}
else {
app().startNode();
}
}
}
}

View File

@@ -1,78 +1,78 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtil.h"
#include "CString.h"
#define WIN32_LEAN_AND_MEAN
#include "Windows.h"
#define ARCH_APPUTIL CArchAppUtilWindows
enum AppExitMode {
kExitModeNormal,
kExitModeDaemon
};
class CArchAppUtilWindows : public CArchAppUtil {
public:
CArchAppUtilWindows();
virtual ~CArchAppUtilWindows();
// Gets the arguments to be used with a service.
CString getServiceArgs() const;
// Install application as Windows service.
void installService();
// Uninstall a Windows service with matching daemon name.
void uninstallService();
// Start a Windows service with matching daemon name.
void startService();
// Stop a Windows service with matching daemon name.
void stopService();
// Will install, uninstall, start, or stop the service depending on arg.
void handleServiceArg(const char* serviceAction);
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "CArchAppUtil.h"
#include "CString.h"
#define WIN32_LEAN_AND_MEAN
#include "Windows.h"
#define ARCH_APPUTIL CArchAppUtilWindows
enum AppExitMode {
kExitModeNormal,
kExitModeDaemon
};
class CArchAppUtilWindows : public CArchAppUtil {
public:
CArchAppUtilWindows();
virtual ~CArchAppUtilWindows();
// Gets the arguments to be used with a service.
CString getServiceArgs() const;
// Install application as Windows service.
void installService();
// Uninstall a Windows service with matching daemon name.
void uninstallService();
// Start a Windows service with matching daemon name.
void startService();
// Stop a Windows service with matching daemon name.
void stopService();
// Will install, uninstall, start, or stop the service depending on arg.
void handleServiceArg(const char* serviceAction);
bool parseArg(const int& argc, const char* const* argv, int& i);
int daemonNTStartup(int, char**);
int daemonNTMainLoop(int argc, const char** argv);
void debugServiceWait();
int daemonNTMainLoop(int argc, const char** argv);
void debugServiceWait();
int run(int argc, char** argv);
void exitApp(int code);
void beforeAppExit();
static CArchAppUtilWindows& instance();
void startNode();
private:
AppExitMode m_exitMode;
static BOOL WINAPI consoleHandler(DWORD CEvent);
};
void exitApp(int code);
void beforeAppExit();
static CArchAppUtilWindows& instance();
void startNode();
private:
AppExitMode m_exitMode;
static BOOL WINAPI consoleHandler(DWORD CEvent);
};

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@
#include "common.h"
#include "stdstring.h"
#include "stdset.h"
#include <windows.h>
#include <windows.h>
#include <Tlhelp32.h>
#include "CString.h"
@@ -174,10 +174,10 @@ public:
static bool wasLaunchedAsService();
//! Returns true if we got the parent process name.
static bool getParentProcessName(CString &name);
static HINSTANCE instanceWin32();
static bool getParentProcessName(CString &name);
static HINSTANCE instanceWin32();
static void setInstanceWin32(HINSTANCE instance);
private:

View File

@@ -1,35 +1,35 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "IInterface.h"
// TODO: replace with forward declaration if possible
// we need to decouple these classes!
#include "CApp.h"
class IArchAppUtil : public IInterface {
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "IInterface.h"
// TODO: replace with forward declaration if possible
// we need to decouple these classes!
#include "CApp.h"
class IArchAppUtil : public IInterface {
public:
virtual bool parseArg(const int& argc, const char* const* argv, int& i) = 0;
virtual void adoptApp(CApp* app) = 0;
virtual CApp& app() const = 0;
virtual int run(int argc, char** argv) = 0;
virtual void beforeAppExit() = 0;
virtual void startNode() = 0;
};
virtual bool parseArg(const int& argc, const char* const* argv, int& i) = 0;
virtual void adoptApp(CApp* app) = 0;
virtual CApp& app() const = 0;
virtual int run(int argc, char** argv) = 0;
virtual void beforeAppExit() = 0;
virtual void startNode() = 0;
};

View File

@@ -1,326 +1,326 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2010 The Synergy+ Project
*
* 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 COPYING 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 "CMSWindowsRelauncher.h"
#include "CThread.h"
#include "TMethodJob.h"
#include "CLog.h"
#include "CArch.h"
#include "Version.h"
#include "CArchDaemonWindows.h"
#include <Tlhelp32.h>
#include <UserEnv.h>
#include <sstream>
CMSWindowsRelauncher::CMSWindowsRelauncher() :
m_thread(NULL)
{
}
CMSWindowsRelauncher::~CMSWindowsRelauncher()
{
delete m_thread;
}
void
CMSWindowsRelauncher::startAsync()
{
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2010 The Synergy+ Project
*
* 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 COPYING 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 "CMSWindowsRelauncher.h"
#include "CThread.h"
#include "TMethodJob.h"
#include "CLog.h"
#include "CArch.h"
#include "Version.h"
#include "CArchDaemonWindows.h"
#include <Tlhelp32.h>
#include <UserEnv.h>
#include <sstream>
CMSWindowsRelauncher::CMSWindowsRelauncher() :
m_thread(NULL)
{
}
CMSWindowsRelauncher::~CMSWindowsRelauncher()
{
delete m_thread;
}
void
CMSWindowsRelauncher::startAsync()
{
m_thread = new CThread(new TMethodJob<CMSWindowsRelauncher>(
this, &CMSWindowsRelauncher::startThread, nullptr));
}
void
CMSWindowsRelauncher::startThread(void*)
{
LOG((CLOG_NOTE "starting relaunch service"));
int ret = relaunchLoop();
// HACK: this actually throws an exception to exit with 0 (nasty)
ARCH->util().app().m_bye(ret);
}
// this still gets the physical session (the one the keyboard and
// mouse is connected to), sometimes this returns -1 but not sure why
DWORD
CMSWindowsRelauncher::getSessionId()
{
return WTSGetActiveConsoleSessionId();
}
BOOL
CMSWindowsRelauncher::winlogonInSession(DWORD sessionId, PHANDLE process)
{
// first we need to take a snapshot of the running processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) {
LOG((CLOG_ERR "could not get process snapshot (error: %i)",
GetLastError()));
return 0;
}
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
// get the first process, and if we can't do that then it's
// unlikely we can go any further
BOOL gotEntry = Process32First(snapshot, &entry);
if (!gotEntry) {
LOG((CLOG_ERR "could not get first process entry (error: %i)",
GetLastError()));
return 0;
}
// used to record process names for debug info
std::list<std::string> nameList;
// now just iterate until we can find winlogon.exe pid
DWORD pid = 0;
while(gotEntry) {
// make sure we're not checking the system process
if (entry.th32ProcessID != 0) {
DWORD processSessionId;
BOOL pidToSidRet = ProcessIdToSessionId(
entry.th32ProcessID, &processSessionId);
if (!pidToSidRet) {
LOG((CLOG_ERR "could not get session id for process id %i (error: %i)",
entry.th32ProcessID, GetLastError()));
return 0;
}
// only pay attention to processes in the active session
if (processSessionId == sessionId) {
// store the names so we can record them for debug
nameList.push_back(entry.szExeFile);
if (_stricmp(entry.szExeFile, "winlogon.exe") == 0) {
pid = entry.th32ProcessID;
break;
}
}
}
// now move on to the next entry (if we're not at the end)
gotEntry = Process32Next(snapshot, &entry);
if (!gotEntry) {
DWORD err = GetLastError();
if (err != ERROR_NO_MORE_FILES) {
// only worry about error if it's not the end of the snapshot
LOG((CLOG_ERR "could not get subsiquent process entry (error: %i)",
GetLastError()));
return 0;
}
}
}
std::string nameListJoin;
for(std::list<std::string>::iterator it = nameList.begin();
it != nameList.end(); it++) {
nameListJoin.append(*it);
nameListJoin.append(", ");
}
LOG((CLOG_DEBUG "checked processes while looking for winlogon.exe: %s",
nameListJoin.c_str()));
CloseHandle(snapshot);
if (pid) {
// now get the process so we can get the process, with which
// we'll use to get the process token.
*process = OpenProcess(MAXIMUM_ALLOWED, FALSE, pid);
return true;
}
else {
LOG((CLOG_DEBUG "could not find winlogon.exe in session %i", sessionId));
return false;
}
}
// gets the current user (so we can launch under their session)
HANDLE
CMSWindowsRelauncher::getCurrentUserToken(DWORD sessionId, LPSECURITY_ATTRIBUTES security)
{
HANDLE currentToken;
HANDLE winlogonProcess;
if (winlogonInSession(sessionId, &winlogonProcess)) {
LOG((CLOG_DEBUG "session %i has winlogon.exe", sessionId));
// get the token, so we can re-launch with this token
// -- do we really need all these access bits?
BOOL tokenRet = OpenProcessToken(
winlogonProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY |
TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY |
TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
&currentToken);
}
else {
LOG((CLOG_ERR "session %i does not have winlogon.exe "
"which is needed for re-launch", sessionId));
return 0;
}
HANDLE primaryToken;
BOOL duplicateRet = DuplicateTokenEx(
currentToken, MAXIMUM_ALLOWED, security,
SecurityImpersonation, TokenPrimary, &primaryToken);
if (!duplicateRet) {
LOG((CLOG_ERR "could not duplicate token %i (error: %i)",
currentToken, GetLastError()));
return 0;
}
return primaryToken;
}
int
CMSWindowsRelauncher::relaunchLoop()
{
// start with invalid id (gets re-assigned on first loop)
DWORD sessionId = -1;
// keep here so we can check if proc running -- huh?
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
int returnCode = kExitSuccess;
bool launched = false;
// TODO: fix this hack BEFORE release; we need to exit gracefully instead
// of being force killed!
bool loopRunning = true;
while (loopRunning) {
DWORD newSessionId = getSessionId();
// only enter here when id changes, and the session isn't -1, which
// may mean that there is no active session.
if ((newSessionId != sessionId) && (newSessionId != -1)) {
// HACK: doesn't close process in a nice way
// TODO: use CloseMainWindow instead
if (launched) {
TerminateProcess(pi.hProcess, kExitSuccess);
LOG((CLOG_DEBUG "terminated existing process to make way for new one"));
launched = false;
}
// ok, this is now the active session (forget the old one if any)
sessionId = newSessionId;
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
// get the token for the user in active session, which is the
// one receiving input from mouse and keyboard.
HANDLE userToken = getCurrentUserToken(sessionId, &sa);
if (userToken != 0) {
LOG((CLOG_DEBUG "got user token to launch new process"));
std::string cmd = getCommand();
// in case reusing process info struct
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default";
LPVOID environment;
BOOL blockRet = CreateEnvironmentBlock(&environment, userToken, FALSE);
if (!blockRet) {
LOG((CLOG_ERR "could not create environment block (error: %i)",
GetLastError()));
returnCode = kExitFailed;
loopRunning = false; // stop loop
}
else {
DWORD creationFlags =
NORMAL_PRIORITY_CLASS |
CREATE_NO_WINDOW |
CREATE_UNICODE_ENVIRONMENT;
// re-launch in current active user session
BOOL createRet = CreateProcessAsUser(
userToken, NULL, LPSTR(cmd.c_str()),
&sa, NULL, TRUE, creationFlags,
environment, NULL, &si, &pi);
DestroyEnvironmentBlock(environment);
CloseHandle(userToken);
if (!createRet) {
LOG((CLOG_ERR "could not launch (error: %i)", GetLastError()));
returnCode = kExitFailed;
loopRunning = false;
}
else {
LOG((CLOG_DEBUG "launched in session %i (cmd: %s)",
sessionId, cmd.c_str()));
launched = true;
}
}
}
}
// check for session change every second
ARCH->sleep(1);
}
if (launched) {
// HACK: kill just in case process it has survived somehow
TerminateProcess(pi.hProcess, kExitSuccess);
}
return kExitSuccess;
}
std::string CMSWindowsRelauncher::getCommand()
{
// seems like a fairly convoluted way to get the process name
const char* launchName = ARCH->util().app().argsBase().m_pname;
std::string args = ((CArchDaemonWindows&)ARCH->daemon()).commandLine();
// build up a full command line
std::stringstream cmdTemp;
cmdTemp << launchName << /*" --debug-data session-" << sessionId <<*/ args;
std::string cmd = cmdTemp.str();
size_t i;
std::string find = "--relaunch";
while((i = cmd.find(find)) != std::string::npos) {
cmd.replace(i, find.length(), "");
}
return cmd;
}
this, &CMSWindowsRelauncher::startThread, nullptr));
}
void
CMSWindowsRelauncher::startThread(void*)
{
LOG((CLOG_NOTE "starting relaunch service"));
int ret = relaunchLoop();
// HACK: this actually throws an exception to exit with 0 (nasty)
ARCH->util().app().m_bye(ret);
}
// this still gets the physical session (the one the keyboard and
// mouse is connected to), sometimes this returns -1 but not sure why
DWORD
CMSWindowsRelauncher::getSessionId()
{
return WTSGetActiveConsoleSessionId();
}
BOOL
CMSWindowsRelauncher::winlogonInSession(DWORD sessionId, PHANDLE process)
{
// first we need to take a snapshot of the running processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) {
LOG((CLOG_ERR "could not get process snapshot (error: %i)",
GetLastError()));
return 0;
}
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
// get the first process, and if we can't do that then it's
// unlikely we can go any further
BOOL gotEntry = Process32First(snapshot, &entry);
if (!gotEntry) {
LOG((CLOG_ERR "could not get first process entry (error: %i)",
GetLastError()));
return 0;
}
// used to record process names for debug info
std::list<std::string> nameList;
// now just iterate until we can find winlogon.exe pid
DWORD pid = 0;
while(gotEntry) {
// make sure we're not checking the system process
if (entry.th32ProcessID != 0) {
DWORD processSessionId;
BOOL pidToSidRet = ProcessIdToSessionId(
entry.th32ProcessID, &processSessionId);
if (!pidToSidRet) {
LOG((CLOG_ERR "could not get session id for process id %i (error: %i)",
entry.th32ProcessID, GetLastError()));
return 0;
}
// only pay attention to processes in the active session
if (processSessionId == sessionId) {
// store the names so we can record them for debug
nameList.push_back(entry.szExeFile);
if (_stricmp(entry.szExeFile, "winlogon.exe") == 0) {
pid = entry.th32ProcessID;
break;
}
}
}
// now move on to the next entry (if we're not at the end)
gotEntry = Process32Next(snapshot, &entry);
if (!gotEntry) {
DWORD err = GetLastError();
if (err != ERROR_NO_MORE_FILES) {
// only worry about error if it's not the end of the snapshot
LOG((CLOG_ERR "could not get subsiquent process entry (error: %i)",
GetLastError()));
return 0;
}
}
}
std::string nameListJoin;
for(std::list<std::string>::iterator it = nameList.begin();
it != nameList.end(); it++) {
nameListJoin.append(*it);
nameListJoin.append(", ");
}
LOG((CLOG_DEBUG "checked processes while looking for winlogon.exe: %s",
nameListJoin.c_str()));
CloseHandle(snapshot);
if (pid) {
// now get the process so we can get the process, with which
// we'll use to get the process token.
*process = OpenProcess(MAXIMUM_ALLOWED, FALSE, pid);
return true;
}
else {
LOG((CLOG_DEBUG "could not find winlogon.exe in session %i", sessionId));
return false;
}
}
// gets the current user (so we can launch under their session)
HANDLE
CMSWindowsRelauncher::getCurrentUserToken(DWORD sessionId, LPSECURITY_ATTRIBUTES security)
{
HANDLE currentToken;
HANDLE winlogonProcess;
if (winlogonInSession(sessionId, &winlogonProcess)) {
LOG((CLOG_DEBUG "session %i has winlogon.exe", sessionId));
// get the token, so we can re-launch with this token
// -- do we really need all these access bits?
BOOL tokenRet = OpenProcessToken(
winlogonProcess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY |
TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY |
TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE,
&currentToken);
}
else {
LOG((CLOG_ERR "session %i does not have winlogon.exe "
"which is needed for re-launch", sessionId));
return 0;
}
HANDLE primaryToken;
BOOL duplicateRet = DuplicateTokenEx(
currentToken, MAXIMUM_ALLOWED, security,
SecurityImpersonation, TokenPrimary, &primaryToken);
if (!duplicateRet) {
LOG((CLOG_ERR "could not duplicate token %i (error: %i)",
currentToken, GetLastError()));
return 0;
}
return primaryToken;
}
int
CMSWindowsRelauncher::relaunchLoop()
{
// start with invalid id (gets re-assigned on first loop)
DWORD sessionId = -1;
// keep here so we can check if proc running -- huh?
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
int returnCode = kExitSuccess;
bool launched = false;
// TODO: fix this hack BEFORE release; we need to exit gracefully instead
// of being force killed!
bool loopRunning = true;
while (loopRunning) {
DWORD newSessionId = getSessionId();
// only enter here when id changes, and the session isn't -1, which
// may mean that there is no active session.
if ((newSessionId != sessionId) && (newSessionId != -1)) {
// HACK: doesn't close process in a nice way
// TODO: use CloseMainWindow instead
if (launched) {
TerminateProcess(pi.hProcess, kExitSuccess);
LOG((CLOG_DEBUG "terminated existing process to make way for new one"));
launched = false;
}
// ok, this is now the active session (forget the old one if any)
sessionId = newSessionId;
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
// get the token for the user in active session, which is the
// one receiving input from mouse and keyboard.
HANDLE userToken = getCurrentUserToken(sessionId, &sa);
if (userToken != 0) {
LOG((CLOG_DEBUG "got user token to launch new process"));
std::string cmd = getCommand();
// in case reusing process info struct
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default";
LPVOID environment;
BOOL blockRet = CreateEnvironmentBlock(&environment, userToken, FALSE);
if (!blockRet) {
LOG((CLOG_ERR "could not create environment block (error: %i)",
GetLastError()));
returnCode = kExitFailed;
loopRunning = false; // stop loop
}
else {
DWORD creationFlags =
NORMAL_PRIORITY_CLASS |
CREATE_NO_WINDOW |
CREATE_UNICODE_ENVIRONMENT;
// re-launch in current active user session
BOOL createRet = CreateProcessAsUser(
userToken, NULL, LPSTR(cmd.c_str()),
&sa, NULL, TRUE, creationFlags,
environment, NULL, &si, &pi);
DestroyEnvironmentBlock(environment);
CloseHandle(userToken);
if (!createRet) {
LOG((CLOG_ERR "could not launch (error: %i)", GetLastError()));
returnCode = kExitFailed;
loopRunning = false;
}
else {
LOG((CLOG_DEBUG "launched in session %i (cmd: %s)",
sessionId, cmd.c_str()));
launched = true;
}
}
}
}
// check for session change every second
ARCH->sleep(1);
}
if (launched) {
// HACK: kill just in case process it has survived somehow
TerminateProcess(pi.hProcess, kExitSuccess);
}
return kExitSuccess;
}
std::string CMSWindowsRelauncher::getCommand()
{
// seems like a fairly convoluted way to get the process name
const char* launchName = ARCH->util().app().argsBase().m_pname;
std::string args = ((CArchDaemonWindows&)ARCH->daemon()).commandLine();
// build up a full command line
std::stringstream cmdTemp;
cmdTemp << launchName << /*" --debug-data session-" << sessionId <<*/ args;
std::string cmd = cmdTemp.str();
size_t i;
std::string find = "--relaunch";
while((i = cmd.find(find)) != std::string::npos) {
cmd.replace(i, find.length(), "");
}
return cmd;
}

View File

@@ -1,38 +1,38 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2010 The Synergy+ Project
*
* 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 COPYING 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
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2010 The Synergy+ Project
*
* 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 COPYING 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 WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <string>
class CThread;
class CMSWindowsRelauncher {
public:
CMSWindowsRelauncher();
virtual ~CMSWindowsRelauncher();
void startAsync();
CThread* m_thread;
void startThread(void*);
BOOL winlogonInSession(DWORD sessionId, PHANDLE process);
DWORD getSessionId();
HANDLE getCurrentUserToken(DWORD sessionId, LPSECURITY_ATTRIBUTES security);
int relaunchLoop();
std::string getCommand();
};
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <string>
class CThread;
class CMSWindowsRelauncher {
public:
CMSWindowsRelauncher();
virtual ~CMSWindowsRelauncher();
void startAsync();
CThread* m_thread;
void startThread(void*);
BOOL winlogonInSession(DWORD sessionId, PHANDLE process);
DWORD getSessionId();
HANDLE getCurrentUserToken(DWORD sessionId, LPSECURITY_ATTRIBUTES security);
int relaunchLoop();
std::string getCommand();
};

View File

@@ -19,25 +19,25 @@
#ifndef CSYNERGYHOOK_H
#define CSYNERGYHOOK_H
// hack: vs2005 doesn't declare _WIN32_WINNT, so we need to hard code it.
// however, some say that this should be hard coded since it defines the
// target system, but since this is suposed to compile on pre-XP, maybe
// we should just leave it like this.
#if _MSC_VER == 1400
#define _WIN32_WINNT 0x0400
#endif
#include "BasicTypes.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// fix: cmake defines the library name in lower case (synrgyhk_EXPORTS) as
// opposed to upper case (SYNRGYHK_EXPORTS), so rather than figuring out
// how to change cmake's behaviour, it's easier to just change the code.
#if defined(synrgyhk_EXPORTS)
#define CSYNERGYHOOK_API __declspec(dllexport)
#else
#define CSYNERGYHOOK_API __declspec(dllimport)
// hack: vs2005 doesn't declare _WIN32_WINNT, so we need to hard code it.
// however, some say that this should be hard coded since it defines the
// target system, but since this is suposed to compile on pre-XP, maybe
// we should just leave it like this.
#if _MSC_VER == 1400
#define _WIN32_WINNT 0x0400
#endif
#include "BasicTypes.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// fix: cmake defines the library name in lower case (synrgyhk_EXPORTS) as
// opposed to upper case (SYNRGYHK_EXPORTS), so rather than figuring out
// how to change cmake's behaviour, it's easier to just change the code.
#if defined(synrgyhk_EXPORTS)
#define CSYNERGYHOOK_API __declspec(dllexport)
#else
#define CSYNERGYHOOK_API __declspec(dllimport)
#endif
#define SYNERGY_MSG_MARK WM_APP + 0x0011 // mark id; <unused>

View File

@@ -160,8 +160,8 @@ private:
// unix daemon mode args
# define HELP_SYS_ARGS \
" [--daemon|--no-daemon]"
# define HELP_SYS_INFO \
" -f, --no-daemon run in the foreground.\n" \
# define HELP_SYS_INFO \
" -f, --no-daemon run in the foreground.\n" \
"* --daemon run as a daemon.\n"
#elif SYSAPI_WIN32

View File

@@ -1,23 +1,23 @@
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "IInterface.h"
class INode : IInterface {
};
/*
* synergy-plus -- mouse and keyboard sharing utility
* Copyright (C) 2009 The Synergy+ Project
* Copyright (C) 2002 Chris Schoeneman
*
* 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 COPYING 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 "IInterface.h"
class INode : IInterface {
};