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