[or-cvs] Forward-port win32 service patch; try to clean it a touch.

Nick Mathewson nickm at seul.org
Thu Jan 27 21:45:35 UTC 2005


Update of /home/or/cvsroot/tor/src/or
In directory moria.mit.edu:/tmp/cvs-serv29557

Modified Files:
	main.c 
Log Message:
Forward-port win32 service patch; try to clean it a touch.

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/main.c,v
retrieving revision 1.428
retrieving revision 1.429
diff -u -d -r1.428 -r1.429
--- main.c	20 Jan 2005 20:21:34 -0000	1.428
+++ main.c	27 Jan 2005 21:45:32 -0000	1.429
@@ -89,6 +89,9 @@
 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 @@
   second_elapsed_callback(0,0,NULL);
 
   for (;;) {
-#ifdef MS_WINDOWS_SERVICE /* Do service stuff only on windows. */
-    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
     /* poll until we have an event, or the second ends */
     loop_result = event_dispatch();
 
@@ -1234,6 +1231,7 @@
 
   /* give it somewhere to log to initially */
   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 @@
 }
 
 #ifdef MS_WINDOWS_SERVICE
+/** If we're compile to run as an NT service, and the service has been
+ * 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_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 @@
   service_status.dwCheckPoint = 0;
   service_status.dwWaitHint = 1000;
   hStatus = RegisterServiceCtrlHandler(GENSRV_SERVICENAME, (LPHANDLER_FUNCTION) nt_service_control);
+
   if (hStatus == 0) {
     // failed;
     return;
   }
+
   err = tor_init(backup_argc, backup_argv); // refactor this part out of tor_main and do_main_loop
   if (err) {
     // failed.
@@ -1376,6 +1391,7 @@
   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 @@
 {
   /* XXXX Problems with NT services:
    * 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 @@
     return 0;
 
   _tsplitpath(szPath, szDrive, szDir, NULL, NULL);
-  len = _MAX_PATH + strlen(cmd1) + _MAX_DRIVE + _MAX_DIR + strlen(cmd2);
+
+  /* Account for the extra quotes */
+  //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);
+  /* Create a quoted command line, like "c:\with spaces\tor.exe" -f
+   * "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 @@
     return 0;
   }
 
+  /* 1/26/2005 mje
+   * - 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;
   }
 
+  /* Start the service initially, so you don't have to muck with it in the SCM
+   */
+  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;
 }



More information about the tor-commits mailing list