Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

CAutoStart.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2002 Chris Schoeneman
00004  * 
00005  * This package is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * found in the file COPYING that should have accompanied this file.
00008  * 
00009  * This package is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
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 // CAutoStartOutputter
00031 //
00032 // This class detects a message above a certain level and saves it
00033 //
00034 
00035 class CAutoStartOutputter : public ILogOutputter {
00036 public:
00037     CAutoStartOutputter(CString* msg) : m_msg(msg) { }
00038     virtual ~CAutoStartOutputter() { }
00039 
00040     // ILogOutputter overrides
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 // CAutoStart
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     // install our log outputter
00086     CLOG->insert(new CAutoStartOutputter(&m_errorMessage));
00087 
00088     // do dialog
00089     DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_AUTOSTART),
00090                                 m_parent, (DLGPROC)dlgProc, (LPARAM)this);
00091 
00092     // remove log outputter
00093     CLOG->pop_front();
00094 }
00095 
00096 void
00097 CAutoStart::reinstallDaemon(bool isClient, const CString& cmdLine)
00098 {
00099     // get installation state
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     // reinstall if anything is installed
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     // open service manager
00159     SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
00160     if (mgr == NULL) {
00161         return false;
00162     }
00163 
00164     // open the service
00165     SC_HANDLE service = OpenService(mgr, name, SERVICE_START);
00166     if (service == NULL) {
00167         CloseServiceHandle(mgr);
00168         return false;
00169     }
00170 
00171     // start the service
00172     BOOL okay = StartService(service, 0, NULL);
00173 
00174     // clean up
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     // get installation state
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     // get user's permissions
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     // update messages
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     // update buttons
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     // get the app path
00264     CString appPath = getAppPath(m_isServer ? SERVER_APP : CLIENT_APP);
00265 
00266     // clear error message
00267     m_errorMessage = "";
00268 
00269     // install
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     // clear error message
00296     m_errorMessage = "";
00297 
00298     // uninstall
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         // save our hwnd
00324         m_hwnd = hwnd;
00325 
00326         // update the controls
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 }

Generated on Fri Nov 6 00:21:13 2009 for synergy-plus by  doxygen 1.3.9.1