source: trunk/synergy/cmd/launcher/CAutoStart.cpp@ 3232

Last change on this file since 3232 was 2749, checked in by bird, 19 years ago

synergy v1.3.1 sources (zip).

File size: 8.2 KB
Line 
1/*
2 * synergy -- mouse and keyboard sharing utility
3 * Copyright (C) 2002 Chris Schoeneman
4 *
5 * This package is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * found in the file COPYING that should have accompanied this file.
8 *
9 * This package is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "CLog.h"
16#include "ILogOutputter.h"
17#include "CArch.h"
18#include "CStringUtil.h"
19#include "XArch.h"
20#include "CAutoStart.h"
21#include "LaunchUtil.h"
22#include "resource.h"
23
24static const char* CLIENT_DAEMON_NAME = "Synergy Client";
25static const char* SERVER_DAEMON_NAME = "Synergy Server";
26static const char* CLIENT_DAEMON_INFO = "Uses a shared mouse and keyboard.";
27static const char* SERVER_DAEMON_INFO = "Shares this system's mouse and keyboard with others.";
28
29//
30// CAutoStartOutputter
31//
32// This class detects a message above a certain level and saves it
33//
34
35class CAutoStartOutputter : public ILogOutputter {
36public:
37 CAutoStartOutputter(CString* msg) : m_msg(msg) { }
38 virtual ~CAutoStartOutputter() { }
39
40 // ILogOutputter overrides
41 virtual void open(const char*) { }
42 virtual void close() { }
43 virtual void show(bool) { }
44 virtual bool write(ELevel level, const char* message);
45 virtual const char* getNewline() const { return ""; }
46
47private:
48 CString* m_msg;
49};
50
51bool
52CAutoStartOutputter::write(ELevel level, const char* message)
53{
54 if (level <= CLog::kERROR) {
55 *m_msg = message;
56 }
57 return false;
58}
59
60
61//
62// CAutoStart
63//
64
65CAutoStart* CAutoStart::s_singleton = NULL;
66
67CAutoStart::CAutoStart(HWND parent, bool isServer, const CString& cmdLine) :
68 m_parent(parent),
69 m_isServer(isServer),
70 m_cmdLine(cmdLine),
71 m_name(isServer ? SERVER_DAEMON_NAME : CLIENT_DAEMON_NAME)
72{
73 assert(s_singleton == NULL);
74 s_singleton = this;
75}
76
77CAutoStart::~CAutoStart()
78{
79 s_singleton = NULL;
80}
81
82void
83CAutoStart::doModal()
84{
85 // install our log outputter
86 CLOG->insert(new CAutoStartOutputter(&m_errorMessage));
87
88 // do dialog
89 DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_AUTOSTART),
90 m_parent, dlgProc, (LPARAM)this);
91
92 // remove log outputter
93 CLOG->pop_front();
94}
95
96void
97CAutoStart::reinstallDaemon(bool isClient, const CString& cmdLine)
98{
99 // get installation state
100 const char* name = (isClient ? CLIENT_DAEMON_NAME : SERVER_DAEMON_NAME);
101 bool installedSystem = ARCH->isDaemonInstalled(name, true);
102 bool installedUser = ARCH->isDaemonInstalled(name, false);
103
104 // reinstall if anything is installed
105 if (installedSystem || installedUser) {
106 ARCH->installDaemon(name,
107 isClient ? CLIENT_DAEMON_INFO : SERVER_DAEMON_INFO,
108 getAppPath(isClient ? CLIENT_APP : SERVER_APP).c_str(),
109 cmdLine.c_str(),
110 NULL,
111 installedSystem);
112 }
113}
114
115void
116CAutoStart::uninstallDaemons(bool client)
117{
118 if (client) {
119 try {
120 ARCH->uninstallDaemon(CLIENT_DAEMON_NAME, true);
121 }
122 catch (...) {
123 }
124 try {
125 ARCH->uninstallDaemon(CLIENT_DAEMON_NAME, false);
126 }
127 catch (...) {
128 }
129 }
130 else {
131 try {
132 ARCH->uninstallDaemon(SERVER_DAEMON_NAME, true);
133 }
134 catch (...) {
135 }
136 try {
137 ARCH->uninstallDaemon(SERVER_DAEMON_NAME, false);
138 }
139 catch (...) {
140 }
141 }
142}
143
144bool
145CAutoStart::startDaemon()
146{
147 const char* name = NULL;
148 if (ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, true)) {
149 name = CLIENT_DAEMON_NAME;
150 }
151 else if (ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, true)) {
152 name = SERVER_DAEMON_NAME;
153 }
154 if (name == NULL) {
155 return false;
156 }
157
158 // open service manager
159 SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
160 if (mgr == NULL) {
161 return false;
162 }
163
164 // open the service
165 SC_HANDLE service = OpenService(mgr, name, SERVICE_START);
166 if (service == NULL) {
167 CloseServiceHandle(mgr);
168 return false;
169 }
170
171 // start the service
172 BOOL okay = StartService(service, 0, NULL);
173
174 // clean up
175 CloseServiceHandle(service);
176 CloseServiceHandle(mgr);
177
178 return (okay != 0);
179}
180
181bool
182CAutoStart::isDaemonInstalled()
183{
184 return (ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, false) ||
185 ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, true) ||
186 ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, false) ||
187 ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, true));
188}
189
190void
191CAutoStart::update()
192{
193 // get installation state
194 const bool installedSystem = ARCH->isDaemonInstalled(
195 m_name.c_str(), true);
196 const bool installedUser = ARCH->isDaemonInstalled(
197 m_name.c_str(), false);
198
199 // get user's permissions
200 const bool canInstallSystem = ARCH->canInstallDaemon(
201 m_name.c_str(), true);
202 const bool canInstallUser = ARCH->canInstallDaemon(
203 m_name.c_str(), false);
204
205 // update messages
206 CString msg, label;
207 if (canInstallSystem) {
208 if (canInstallUser) {
209 msg = getString(IDS_AUTOSTART_PERMISSION_ALL);
210 }
211 else {
212 msg = getString(IDS_AUTOSTART_PERMISSION_SYSTEM);
213 }
214 }
215 else if (canInstallUser) {
216 msg = getString(IDS_AUTOSTART_PERMISSION_USER);
217 }
218 else {
219 msg = getString(IDS_AUTOSTART_PERMISSION_NONE);
220 }
221 setWindowText(getItem(m_hwnd, IDC_AUTOSTART_PERMISSION_MSG), msg);
222 if (installedSystem) {
223 msg = getString(IDS_AUTOSTART_INSTALLED_SYSTEM);
224 label = getString(IDS_UNINSTALL_LABEL);
225 }
226 else if (installedUser) {
227 msg = getString(IDS_AUTOSTART_INSTALLED_USER);
228 label = getString(IDS_UNINSTALL_LABEL);
229 }
230 else {
231 msg = getString(IDS_AUTOSTART_INSTALLED_NONE);
232 label = getString(IDS_INSTALL_LABEL);
233 }
234 setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALLED_MSG), msg);
235
236 // update buttons
237 setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM), label);
238 setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER), label);
239 if (installedSystem) {
240 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, canInstallSystem);
241 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, false);
242 m_install = false;
243 }
244 else if (installedUser) {
245 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, false);
246 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, canInstallUser);
247 m_install = false;
248 }
249 else {
250 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, canInstallSystem);
251 enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, canInstallUser);
252 m_install = true;
253 }
254}
255
256bool
257CAutoStart::onInstall(bool allUsers)
258{
259 if (!m_install) {
260 return onUninstall(allUsers);
261 }
262
263 // get the app path
264 CString appPath = getAppPath(m_isServer ? SERVER_APP : CLIENT_APP);
265
266 // clear error message
267 m_errorMessage = "";
268
269 // install
270 try {
271 ARCH->installDaemon(m_name.c_str(),
272 m_isServer ? SERVER_DAEMON_INFO : CLIENT_DAEMON_INFO,
273 appPath.c_str(), m_cmdLine.c_str(),
274 NULL, allUsers);
275 askOkay(m_hwnd, getString(IDS_INSTALL_TITLE),
276 getString(allUsers ?
277 IDS_INSTALLED_SYSTEM :
278 IDS_INSTALLED_USER));
279 return true;
280 }
281 catch (XArchDaemon& e) {
282 if (m_errorMessage.empty()) {
283 m_errorMessage = CStringUtil::format(
284 getString(IDS_INSTALL_GENERIC_ERROR).c_str(),
285 e.what().c_str());
286 }
287 showError(m_hwnd, m_errorMessage);
288 return false;
289 }
290}
291
292bool
293CAutoStart::onUninstall(bool allUsers)
294{
295 // clear error message
296 m_errorMessage = "";
297
298 // uninstall
299 try {
300 ARCH->uninstallDaemon(m_name.c_str(), allUsers);
301 askOkay(m_hwnd, getString(IDS_UNINSTALL_TITLE),
302 getString(allUsers ?
303 IDS_UNINSTALLED_SYSTEM :
304 IDS_UNINSTALLED_USER));
305 return true;
306 }
307 catch (XArchDaemon& e) {
308 if (m_errorMessage.empty()) {
309 m_errorMessage = CStringUtil::format(
310 getString(IDS_UNINSTALL_GENERIC_ERROR).c_str(),
311 e.what().c_str());
312 }
313 showError(m_hwnd, m_errorMessage);
314 return false;
315 }
316}
317
318BOOL
319CAutoStart::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM)
320{
321 switch (message) {
322 case WM_INITDIALOG:
323 // save our hwnd
324 m_hwnd = hwnd;
325
326 // update the controls
327 update();
328
329 return TRUE;
330
331 case WM_COMMAND:
332 switch (LOWORD(wParam)) {
333 case IDC_AUTOSTART_INSTALL_SYSTEM:
334 onInstall(true);
335 update();
336 return TRUE;
337
338 case IDC_AUTOSTART_INSTALL_USER:
339 onInstall(false);
340 update();
341 return TRUE;
342
343 case IDCANCEL:
344 EndDialog(hwnd, 0);
345 m_hwnd = NULL;
346 return TRUE;
347 }
348 break;
349
350 default:
351 break;
352 }
353
354 return FALSE;
355}
356
357BOOL CALLBACK
358CAutoStart::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
359{
360 return s_singleton->doDlgProc(hwnd, message, wParam, lParam);
361}
Note: See TracBrowser for help on using the repository browser.