|
@@ -89,6 +89,9 @@ SERVICE_STATUS service_status;
|
|
|
SERVICE_STATUS_HANDLE hStatus;
|
|
|
static char **backup_argv;
|
|
|
static int backup_argc;
|
|
|
+static int nt_service_is_stopped(void);
|
|
|
+#else
|
|
|
+#define nt_service_is_stopped() (0)
|
|
|
#endif
|
|
|
|
|
|
#define CHECK_DESCRIPTOR_INTERVAL 60
|
|
@@ -982,14 +985,8 @@ static int do_main_loop(void) {
|
|
|
second_elapsed_callback(0,0,NULL);
|
|
|
|
|
|
for (;;) {
|
|
|
-#ifdef MS_WINDOWS_SERVICE
|
|
|
- if (service_status.dwCurrentState == SERVICE_STOP_PENDING) {
|
|
|
- service_status.dwWin32ExitCode = 0;
|
|
|
- service_status.dwCurrentState = SERVICE_STOPPED;
|
|
|
- SetServiceStatus(hStatus, &service_status);
|
|
|
+ if (nt_service_is_stopped())
|
|
|
return 0;
|
|
|
- }
|
|
|
-#endif
|
|
|
|
|
|
loop_result = event_dispatch();
|
|
|
|
|
@@ -1234,6 +1231,7 @@ static int tor_init(int argc, char *argv[]) {
|
|
|
|
|
|
|
|
|
add_temp_log();
|
|
|
+
|
|
|
log_fn(LOG_NOTICE,"Tor v%s. This is experimental software. Do not rely on it for strong anonymity.",VERSION);
|
|
|
|
|
|
if (network_init()<0) {
|
|
@@ -1324,6 +1322,22 @@ static void do_hash_password(void)
|
|
|
}
|
|
|
|
|
|
#ifdef MS_WINDOWS_SERVICE
|
|
|
+
|
|
|
+ * shut down, then change our current status and return 1. Else
|
|
|
+ * return 0.
|
|
|
+ */
|
|
|
+static int
|
|
|
+nt_service_is_stopped(void)
|
|
|
+{
|
|
|
+ if (service_status.dwCurrentState == SERVICE_STOP_PENDING) {
|
|
|
+ service_status.dwWin32ExitCode = 0;
|
|
|
+ service_status.dwCurrentState = SERVICE_STOPPED;
|
|
|
+ SetServiceStatus(hStatus, &service_status);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
void nt_service_control(DWORD request)
|
|
|
{
|
|
|
switch (request) {
|
|
@@ -1339,7 +1353,6 @@ void nt_service_control(DWORD request)
|
|
|
void nt_service_body(int argc, char **argv)
|
|
|
{
|
|
|
int err;
|
|
|
- FILE *f;
|
|
|
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
|
service_status.dwCurrentState = SERVICE_START_PENDING;
|
|
|
service_status.dwControlsAccepted =
|
|
@@ -1349,10 +1362,12 @@ void nt_service_body(int argc, char **argv)
|
|
|
service_status.dwCheckPoint = 0;
|
|
|
service_status.dwWaitHint = 1000;
|
|
|
hStatus = RegisterServiceCtrlHandler(GENSRV_SERVICENAME, (LPHANDLER_FUNCTION) nt_service_control);
|
|
|
+
|
|
|
if (hStatus == 0) {
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
err = tor_init(backup_argc, backup_argv);
|
|
|
if (err) {
|
|
|
|
|
@@ -1376,6 +1391,7 @@ void nt_service_main(void)
|
|
|
table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body;
|
|
|
table[1].lpServiceName = NULL;
|
|
|
table[1].lpServiceProc = NULL;
|
|
|
+
|
|
|
if (!StartServiceCtrlDispatcher(table)) {
|
|
|
result = GetLastError();
|
|
|
printf("Error was %d\n",result);
|
|
@@ -1404,11 +1420,15 @@ int nt_service_install()
|
|
|
{
|
|
|
|
|
|
* 1. The configuration file needs to be in the same directory as the .exe
|
|
|
+ *
|
|
|
* 2. The exe and the configuration file can't be on any directory path
|
|
|
* that contains a space.
|
|
|
+ * mje - you can quote the string (i.e., "c:\program files")
|
|
|
+ *
|
|
|
* 3. Ideally, there should be one EXE that can either run as a
|
|
|
* separate process (as now) or that can install and run itself
|
|
|
* as an NT service. I have no idea how hard this is.
|
|
|
+ * mje - should be done. It can install and run itself as a service
|
|
|
*
|
|
|
* Notes about developing NT services:
|
|
|
*
|
|
@@ -1432,14 +1452,21 @@ int nt_service_install()
|
|
|
return 0;
|
|
|
|
|
|
_tsplitpath(szPath, szDrive, szDir, NULL, NULL);
|
|
|
- len = _MAX_PATH + strlen(cmd1) + _MAX_DRIVE + _MAX_DIR + strlen(cmd2);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ len = _MAX_PATH + strlen(cmd1) + _MAX_DRIVE + _MAX_DIR + strlen(cmd2) + 4;
|
|
|
command = tor_malloc(len);
|
|
|
|
|
|
- strlcpy(command, szPath, len);
|
|
|
- strlcat(command, " -f ", len);
|
|
|
- strlcat(command, szDrive, len);
|
|
|
- strlcat(command, szDir, len);
|
|
|
- strlcat(command, "\\torrc", len);
|
|
|
+
|
|
|
+ * "c:\with spaces\tor.exe"
|
|
|
+ */
|
|
|
+ if (tor_snprintf(command, len, "\"%s\" -f \"%s%storrc\"",
|
|
|
+ szPath, szDrive, szDir)<0) {
|
|
|
+ printf("Failed: tor_snprinf()\n");
|
|
|
+ free(command);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
if ((hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) {
|
|
|
printf("Failed: OpenSCManager()\n");
|
|
@@ -1447,21 +1474,31 @@ int nt_service_install()
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * - changed the service start type to auto
|
|
|
+ * - and changed the lpPassword param to "" instead of NULL as per an
|
|
|
+ * MSDN article.
|
|
|
+ */
|
|
|
if ((hService = CreateService(hSCManager, GENSRV_SERVICENAME, GENSRV_DISPLAYNAME,
|
|
|
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
|
|
|
- SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, command,
|
|
|
- NULL, NULL, NULL, NULL, NULL)) == NULL) {
|
|
|
+ SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, command,
|
|
|
+ NULL, NULL, NULL, NULL, "")) == NULL) {
|
|
|
printf("Failed: CreateService()\n");
|
|
|
CloseServiceHandle(hSCManager);
|
|
|
free(command);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ */
|
|
|
+ if(!StartService(hService, 0, NULL))
|
|
|
+ printf("Service installed, but not started.\n");
|
|
|
+ else
|
|
|
+ printf("Service installed and started successfully!\n");
|
|
|
+
|
|
|
CloseServiceHandle(hService);
|
|
|
CloseServiceHandle(hSCManager);
|
|
|
- free(command);
|
|
|
-
|
|
|
- printf("Install service successfully\n");
|
|
|
+ tor_free(command);
|
|
|
|
|
|
return 0;
|
|
|
}
|