00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <QLibrary>
00029 #include <vidalia.h>
00030
00031 #include "torservice.h"
00032
00033
00034
00035 #define UNKNOWN_EXIT_CODE -999999
00036
00037
00038 ServiceFunctions TorService::_service_fns =
00039 { false,
00040 NULL, NULL, NULL, NULL, NULL,
00041 NULL, NULL, NULL, NULL, NULL };
00042
00043
00044
00045 TorService::TorService(QObject *parent)
00046 : QObject(parent)
00047 {
00048 _scm = openSCM();
00049 }
00050
00051
00052 TorService::~TorService()
00053 {
00054 closeHandle(_scm);
00055 }
00056
00057
00058 bool
00059 TorService::isSupported()
00060 {
00061 return (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based);
00062 }
00063
00064
00065
00066
00067 bool
00068 TorService::loadServiceFunctions()
00069 {
00070 #define LOAD_SERVICE_FN(f) do { \
00071 void *fn; \
00072 if (!((fn = QLibrary::resolve("advapi32", #f)))) { \
00073 vWarn("Unable to load NT service function: %1").arg(#f); \
00074 return false; \
00075 } else { \
00076 _service_fns.f = (f ## _fn) fn; \
00077 } \
00078 } while (0)
00079
00080 if (!isSupported()) {
00081 _service_fns.loaded = false;
00082 } else if (!_service_fns.loaded) {
00083 LOAD_SERVICE_FN(ChangeServiceConfig2A);
00084 LOAD_SERVICE_FN(CloseServiceHandle);
00085 LOAD_SERVICE_FN(ControlService);
00086 LOAD_SERVICE_FN(CreateServiceA);
00087 LOAD_SERVICE_FN(DeleteService);
00088 LOAD_SERVICE_FN(OpenSCManagerA);
00089 LOAD_SERVICE_FN(OpenServiceA);
00090 LOAD_SERVICE_FN(QueryServiceStatus);
00091 LOAD_SERVICE_FN(SetServiceStatus);
00092 LOAD_SERVICE_FN(StartServiceA);
00093 _service_fns.loaded = true;
00094 }
00095 return _service_fns.loaded;
00096 }
00097
00098
00099 SC_HANDLE
00100 TorService::openService()
00101 {
00102 if (!loadServiceFunctions())
00103 return NULL;
00104 if (!_scm)
00105 return NULL;
00106 return _service_fns.OpenServiceA(_scm,
00107 (LPCTSTR)TOR_SERVICE_NAME,
00108 TOR_SERVICE_ACCESS);
00109 }
00110
00111
00112 SC_HANDLE
00113 TorService::openSCM()
00114 {
00115 if (!loadServiceFunctions())
00116 return NULL;
00117 return _service_fns.OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
00118 }
00119
00120
00121 void
00122 TorService::closeHandle(SC_HANDLE handle)
00123 {
00124 if (!loadServiceFunctions())
00125 return;
00126 _service_fns.CloseServiceHandle(handle);
00127 }
00128
00129
00130 bool
00131 TorService::isInstalled()
00132 {
00133 bool installed;
00134 SC_HANDLE service = openService();
00135 installed = (service != NULL);
00136 closeHandle(service);
00137 return installed;
00138 }
00139
00140
00141 bool
00142 TorService::isRunning()
00143 {
00144 return (status() == SERVICE_RUNNING);
00145 }
00146
00147
00148 void
00149 TorService::start()
00150 {
00151 SC_HANDLE service = openService();
00152
00153 if (!service) {
00154 vWarn("Bug: We tried to start the Tor service, but it is not installed.");
00155 emit startFailed(tr("The Tor service is not installed."));
00156 return;
00157 }
00158
00159
00160 if (status() != SERVICE_RUNNING) {
00161 int tries = 0;
00162 vNotice("Starting the Tor service.");
00163 _service_fns.StartServiceA(service, 0, NULL);
00164
00165 while ((status() != SERVICE_RUNNING) && ++tries <= 5)
00166 Sleep(1000);
00167 }
00168
00169 if (status() == SERVICE_RUNNING) {
00170 emit started();
00171 } else {
00172 vWarn("Unable to start the Tor service.");
00173 emit startFailed(tr("Unable to start the Tor service."));
00174 }
00175 closeHandle(service);
00176 }
00177
00178
00179 bool
00180 TorService::stop()
00181 {
00182 SC_HANDLE service = openService();
00183
00184 if (!service)
00185 return false;
00186
00187 if (status() != SERVICE_STOPPED) {
00188 SERVICE_STATUS stat;
00189 stat.dwCurrentState = SERVICE_RUNNING;
00190 vNotice("Stopping the Tor service.");
00191 if (_service_fns.ControlService(service, SERVICE_CONTROL_STOP, &stat)) {
00192
00193
00194
00195
00196 int tries = 0;
00197 while ((status() != SERVICE_STOPPED) && (++tries <= 5))
00198 Sleep(1000);
00199 }
00200 }
00201 closeHandle(service);
00202
00203
00204 if (status() == SERVICE_STOPPED) {
00205 emit finished(exitCode(), exitStatus());
00206 return true;
00207 }
00208
00209 vWarn("Unable to stop the Tor service.");
00210 return false;
00211 }
00212
00213
00214 int
00215 TorService::exitCode()
00216 {
00217 SC_HANDLE service;
00218 int exitCode = UNKNOWN_EXIT_CODE;
00219
00220 service = openService();
00221 if (service) {
00222 SERVICE_STATUS s;
00223 if (_service_fns.QueryServiceStatus(service, &s)) {
00224
00225
00226 exitCode = (int)(s.dwWin32ExitCode == ERROR_SERVICE_SPECIFIC_ERROR
00227 ? s.dwServiceSpecificExitCode
00228 : s.dwWin32ExitCode);
00229 }
00230 closeHandle(service);
00231 }
00232 return exitCode;
00233 }
00234
00235
00236 QProcess::ExitStatus
00237 TorService::exitStatus()
00238 {
00239
00240
00241
00242
00243
00244
00245 return QProcess::NormalExit;
00246 }
00247
00248
00249
00250 bool
00251 TorService::install(const QString &torPath, const QString &torrc,
00252 quint16 controlPort)
00253 {
00254 SC_HANDLE service;
00255
00256 if (!_scm)
00257 return false;
00258
00259 service = openService();
00260 if (!service) {
00261 QString command = QString("\"%1\" --nt-service -f \"%2\" ControlPort %3")
00262 .arg(torPath)
00263 .arg(torrc)
00264 .arg(controlPort);
00265
00266 vNotice("Installing the Tor service using the command line '%1'")
00267 .arg(command);
00268 service = _service_fns.CreateServiceA(_scm,
00269 (LPCTSTR)TOR_SERVICE_NAME, (LPCTSTR)TOR_SERVICE_DISP,
00270 TOR_SERVICE_ACCESS, SERVICE_WIN32_OWN_PROCESS,
00271 SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
00272 (LPCTSTR)command.toAscii().data(), NULL, NULL, NULL,
00273 NULL, NULL);
00274 if (!service) {
00275
00276 vWarn("Failed to install the Tor service.");
00277 return false;
00278 }
00279
00280 SERVICE_DESCRIPTION desc;
00281 desc.lpDescription = TOR_SERVICE_DESC;
00282 _service_fns.ChangeServiceConfig2A(service,
00283 SERVICE_CONFIG_DESCRIPTION, &desc);
00284 closeHandle(service);
00285 }
00286 return true;
00287 }
00288
00289
00290
00291 bool
00292 TorService::remove()
00293 {
00294 bool removed = true;
00295 SC_HANDLE service = openService();
00296
00297 if (service) {
00298 stop();
00299 vNotice("Removing the Tor service.");
00300 removed = _service_fns.DeleteService(service);
00301 closeHandle(service);
00302 }
00303 if (!removed) {
00304
00305 vWarn("Failed to remove the Tor service.");
00306 }
00307 return removed;
00308 }
00309
00310
00311 DWORD
00312 TorService::status()
00313 {
00314 SC_HANDLE service;
00315 SERVICE_STATUS s;
00316 DWORD stat = SERVICE_ERROR;
00317
00318 service = openService();
00319 if (service && _service_fns.QueryServiceStatus(service, &s))
00320 stat = s.dwCurrentState;
00321 closeHandle(service);
00322 return stat;
00323 }
00324