00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "CLog.h"
00016 #include "ILogOutputter.h"
00017 #include "CArch.h"
00018 #include "CStringUtil.h"
00019 #include "XArch.h"
00020 #include "CAutoStart.h"
00021 #include "LaunchUtil.h"
00022 #include "resource.h"
00023
00024 static const char* CLIENT_DAEMON_NAME = "Synergy Client";
00025 static const char* SERVER_DAEMON_NAME = "Synergy Server";
00026 static const char* CLIENT_DAEMON_INFO = "Uses a shared mouse and keyboard.";
00027 static const char* SERVER_DAEMON_INFO = "Shares this system's mouse and keyboard with others.";
00028
00029
00030
00031
00032
00033
00034
00035 class CAutoStartOutputter : public ILogOutputter {
00036 public:
00037 CAutoStartOutputter(CString* msg) : m_msg(msg) { }
00038 virtual ~CAutoStartOutputter() { }
00039
00040
00041 virtual void open(const char*) { }
00042 virtual void close() { }
00043 virtual void show(bool) { }
00044 virtual bool write(ELevel level, const char* message);
00045 virtual const char* getNewline() const { return ""; }
00046
00047 private:
00048 CString* m_msg;
00049 };
00050
00051 bool
00052 CAutoStartOutputter::write(ELevel level, const char* message)
00053 {
00054 if (level <= CLog::kERROR) {
00055 *m_msg = message;
00056 }
00057 return false;
00058 }
00059
00060
00061
00062
00063
00064
00065 CAutoStart* CAutoStart::s_singleton = NULL;
00066
00067 CAutoStart::CAutoStart(HWND parent, bool isServer, const CString& cmdLine) :
00068 m_parent(parent),
00069 m_isServer(isServer),
00070 m_cmdLine(cmdLine),
00071 m_name(isServer ? SERVER_DAEMON_NAME : CLIENT_DAEMON_NAME)
00072 {
00073 assert(s_singleton == NULL);
00074 s_singleton = this;
00075 }
00076
00077 CAutoStart::~CAutoStart()
00078 {
00079 s_singleton = NULL;
00080 }
00081
00082 void
00083 CAutoStart::doModal()
00084 {
00085
00086 CLOG->insert(new CAutoStartOutputter(&m_errorMessage));
00087
00088
00089 DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_AUTOSTART),
00090 m_parent, (DLGPROC)dlgProc, (LPARAM)this);
00091
00092
00093 CLOG->pop_front();
00094 }
00095
00096 void
00097 CAutoStart::reinstallDaemon(bool isClient, const CString& cmdLine)
00098 {
00099
00100 const char* name = (isClient ? CLIENT_DAEMON_NAME : SERVER_DAEMON_NAME);
00101 bool installedSystem = ARCH->isDaemonInstalled(name, true);
00102 bool installedUser = ARCH->isDaemonInstalled(name, false);
00103
00104
00105 if (installedSystem || installedUser) {
00106 ARCH->installDaemon(name,
00107 isClient ? CLIENT_DAEMON_INFO : SERVER_DAEMON_INFO,
00108 getAppPath(isClient ? CLIENT_APP : SERVER_APP).c_str(),
00109 cmdLine.c_str(),
00110 NULL,
00111 installedSystem);
00112 }
00113 }
00114
00115 void
00116 CAutoStart::uninstallDaemons(bool client)
00117 {
00118 if (client) {
00119 try {
00120 ARCH->uninstallDaemon(CLIENT_DAEMON_NAME, true);
00121 }
00122 catch (...) {
00123 }
00124 try {
00125 ARCH->uninstallDaemon(CLIENT_DAEMON_NAME, false);
00126 }
00127 catch (...) {
00128 }
00129 }
00130 else {
00131 try {
00132 ARCH->uninstallDaemon(SERVER_DAEMON_NAME, true);
00133 }
00134 catch (...) {
00135 }
00136 try {
00137 ARCH->uninstallDaemon(SERVER_DAEMON_NAME, false);
00138 }
00139 catch (...) {
00140 }
00141 }
00142 }
00143
00144 bool
00145 CAutoStart::startDaemon()
00146 {
00147 const char* name = NULL;
00148 if (ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, true)) {
00149 name = CLIENT_DAEMON_NAME;
00150 }
00151 else if (ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, true)) {
00152 name = SERVER_DAEMON_NAME;
00153 }
00154 if (name == NULL) {
00155 return false;
00156 }
00157
00158
00159 SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
00160 if (mgr == NULL) {
00161 return false;
00162 }
00163
00164
00165 SC_HANDLE service = OpenService(mgr, name, SERVICE_START);
00166 if (service == NULL) {
00167 CloseServiceHandle(mgr);
00168 return false;
00169 }
00170
00171
00172 BOOL okay = StartService(service, 0, NULL);
00173
00174
00175 CloseServiceHandle(service);
00176 CloseServiceHandle(mgr);
00177
00178 return (okay != 0);
00179 }
00180
00181 bool
00182 CAutoStart::isDaemonInstalled()
00183 {
00184 return (ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, false) ||
00185 ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, true) ||
00186 ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, false) ||
00187 ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, true));
00188 }
00189
00190 void
00191 CAutoStart::update()
00192 {
00193
00194 const bool installedSystem = ARCH->isDaemonInstalled(
00195 m_name.c_str(), true);
00196 const bool installedUser = ARCH->isDaemonInstalled(
00197 m_name.c_str(), false);
00198
00199
00200 const bool canInstallSystem = ARCH->canInstallDaemon(
00201 m_name.c_str(), true);
00202 const bool canInstallUser = ARCH->canInstallDaemon(
00203 m_name.c_str(), false);
00204
00205
00206 CString msg, label;
00207 if (canInstallSystem) {
00208 if (canInstallUser) {
00209 msg = getString(IDS_AUTOSTART_PERMISSION_ALL);
00210 }
00211 else {
00212 msg = getString(IDS_AUTOSTART_PERMISSION_SYSTEM);
00213 }
00214 }
00215 else if (canInstallUser) {
00216 msg = getString(IDS_AUTOSTART_PERMISSION_USER);
00217 }
00218 else {
00219 msg = getString(IDS_AUTOSTART_PERMISSION_NONE);
00220 }
00221 setWindowText(getItem(m_hwnd, IDC_AUTOSTART_PERMISSION_MSG), msg);
00222 if (installedSystem) {
00223 msg = getString(IDS_AUTOSTART_INSTALLED_SYSTEM);
00224 label = getString(IDS_UNINSTALL_LABEL);
00225 }
00226 else if (installedUser) {
00227 msg = getString(IDS_AUTOSTART_INSTALLED_USER);
00228 label = getString(IDS_UNINSTALL_LABEL);
00229 }
00230 else {
00231 msg = getString(IDS_AUTOSTART_INSTALLED_NONE);
00232 label = getString(IDS_INSTALL_LABEL);
00233 }
00234 setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALLED_MSG), msg);
00235
00236
00237 setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM), label);
00238 setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER), label);
00239 if (installedSystem) {
00240 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, canInstallSystem);
00241 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, false);
00242 m_install = false;
00243 }
00244 else if (installedUser) {
00245 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, false);
00246 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, canInstallUser);
00247 m_install = false;
00248 }
00249 else {
00250 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, canInstallSystem);
00251 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, canInstallUser);
00252 m_install = true;
00253 }
00254 }
00255
00256 bool
00257 CAutoStart::onInstall(bool allUsers)
00258 {
00259 if (!m_install) {
00260 return onUninstall(allUsers);
00261 }
00262
00263
00264 CString appPath = getAppPath(m_isServer ? SERVER_APP : CLIENT_APP);
00265
00266
00267 m_errorMessage = "";
00268
00269
00270 try {
00271 ARCH->installDaemon(m_name.c_str(),
00272 m_isServer ? SERVER_DAEMON_INFO : CLIENT_DAEMON_INFO,
00273 appPath.c_str(), m_cmdLine.c_str(),
00274 NULL, allUsers);
00275 askOkay(m_hwnd, getString(IDS_INSTALL_TITLE),
00276 getString(allUsers ?
00277 IDS_INSTALLED_SYSTEM :
00278 IDS_INSTALLED_USER));
00279 return true;
00280 }
00281 catch (XArchDaemon& e) {
00282 if (m_errorMessage.empty()) {
00283 m_errorMessage = CStringUtil::format(
00284 getString(IDS_INSTALL_GENERIC_ERROR).c_str(),
00285 e.what().c_str());
00286 }
00287 showError(m_hwnd, m_errorMessage);
00288 return false;
00289 }
00290 }
00291
00292 bool
00293 CAutoStart::onUninstall(bool allUsers)
00294 {
00295
00296 m_errorMessage = "";
00297
00298
00299 try {
00300 ARCH->uninstallDaemon(m_name.c_str(), allUsers);
00301 askOkay(m_hwnd, getString(IDS_UNINSTALL_TITLE),
00302 getString(allUsers ?
00303 IDS_UNINSTALLED_SYSTEM :
00304 IDS_UNINSTALLED_USER));
00305 return true;
00306 }
00307 catch (XArchDaemon& e) {
00308 if (m_errorMessage.empty()) {
00309 m_errorMessage = CStringUtil::format(
00310 getString(IDS_UNINSTALL_GENERIC_ERROR).c_str(),
00311 e.what().c_str());
00312 }
00313 showError(m_hwnd, m_errorMessage);
00314 return false;
00315 }
00316 }
00317
00318 BOOL
00319 CAutoStart::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
00320 {
00321 switch (message) {
00322 case WM_INITDIALOG:
00323
00324 m_hwnd = hwnd;
00325
00326
00327 update();
00328
00329 return TRUE;
00330
00331 case WM_COMMAND:
00332 switch (LOWORD(wParam)) {
00333 case IDC_AUTOSTART_INSTALL_SYSTEM:
00334 onInstall(true);
00335 update();
00336 return TRUE;
00337
00338 case IDC_AUTOSTART_INSTALL_USER:
00339 onInstall(false);
00340 update();
00341 return TRUE;
00342
00343 case IDCANCEL:
00344 EndDialog(hwnd, 0);
00345 m_hwnd = NULL;
00346 return TRUE;
00347 }
00348 break;
00349
00350 default:
00351 break;
00352 }
00353
00354 return FALSE;
00355 }
00356
00357 BOOL CALLBACK
00358 CAutoStart::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
00359 {
00360 return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
00361 }