[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r8643: Try to make mingw capable of producing a working tor binary (in tor/trunk: . src/or)



Author: nickm
Date: 2006-10-07 20:33:35 -0400 (Sat, 07 Oct 2006)
New Revision: 8643

Modified:
   tor/trunk/
   tor/trunk/src/or/main.c
Log:
 r8932@totoro:  nickm | 2006-10-07 20:29:03 -0400
 Try to make mingw capable of producing a working tor binary for win98: make all NT-service-related functions get lazy-loaded on demand.  I have no idea if this even compiles.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r8932] on 96637b51-b116-0410-a10e-9941ebb49b64

Modified: tor/trunk/src/or/main.c
===================================================================
--- tor/trunk/src/or/main.c	2006-10-07 19:56:49 UTC (rev 8642)
+++ tor/trunk/src/or/main.c	2006-10-08 00:33:35 UTC (rev 8643)
@@ -1654,6 +1654,117 @@
 }
 
 #ifdef MS_WINDOWS_SERVICE
+
+struct service_fns {
+  int loaded;
+
+  BOOL WINAPI (ChangeServiceConfig2_fn*)(
+                             SC_HANDLE hService,
+                             DWORD dwInfoLevel,
+                             LPVOID lpInfo);
+
+  BOOL WINAPI (CloseServiceHandle_fn*)(
+                             SC_HANDLE hSCObject);
+
+  BOOL WINAPI (ControlService_fn*)(
+                             SC_HANDLE hService,
+                             DWORD dwControl,
+                             LPSERVICE_STATUS lpServiceStatus);
+
+  SC_HANDLE WINAPI (CreateService_fn*)(
+                             SC_HANDLE hSCManager,
+                             LPCTSTR lpServiceName,
+                             LPCTSTR lpDisplayName,
+                             DWORD dwDesiredAccess,
+                             DWORD dwServiceType,
+                             DWORD dwStartType,
+                             DWORD dwErrorControl,
+                             LPCTSTR lpBinaryPathName,
+                             LPCTSTR lpLoadOrderGroup,
+                             LPDWORD lpdwTagId,
+                             LPCTSTR lpDependencies,
+                             LPCTSTR lpServiceStartName,
+                             LPCTSTR lpPassword);
+
+  BOOL WINAPI (DeleteService_fn*)(
+                             SC_HANDLE hService);
+
+  SC_HANDLE WINAPI (OpenSCManager_fn*)(
+                             LPCTSTR lpMachineName,
+                             LPCTSTR lpDatabaseName,
+                             DWORD dwDesiredAccess);
+
+  SC_HANDLE WINAPI (OpenService_fn*)(
+                             SC_HANDLE hSCManager,
+                             LPCTSTR lpServiceName,
+                             DWORD dwDesiredAccess);
+
+  BOOL WINAPI (QueryServiceStatus_fn*)(
+                             SC_HANDLE hService,
+                             LPSERVICE_STATUS lpServiceStatus);
+
+  SERVICE_STATUS_HANDLE WINAPI (RegisterServiceCtrlHandler_fn*)(
+                             LPCTSTR lpServiceName,
+                             LPHANDLER_FUNCTION lpHandlerProc);
+
+  BOOL WINAPI (SetServiceStatus_fn*)(SERVICE_STATUS_HANDLE,
+                             LPSERVICE_STATUS);
+
+  BOOL WINAPI (StartServiceCtrlDispatcher_fn*)(
+                             const SERVICE_TABLE_ENTRY* lpServiceTable);
+
+  BOOL WINAPI (StartService_fn*)(
+                             SC_HANDLE hService,
+                             DWORD dwNumServiceArgs,
+                             LPCTSTR* lpServiceArgVectors);
+
+} service_fns = { 0,
+                  NULL, NULL, NULL, NULL, NULL, NULL,
+                  NULL, NULL, NULL, NULL, NULL, NULL, };
+
+static int
+nt_service_loadlibrary(void)
+{
+  HMODULE library = 0;
+  void *fn;
+
+  if (loaded)
+    return 0;
+
+  if (!(library = LoadLibrary("advapi32.dll"))) {
+    log_err(LD_GENERAL, "Couldn't open advapi32.dll.  Are you trying to use "
+            "NT services on Windows 98? That doesn't work.");
+    return -1;
+  }
+
+#define LOAD(f) do {                                                    \
+    if (!(fn = GetProcAddress(library, #f))) {                          \
+      log_err(LD_BUF, "Couldn't find %s in advapi32.dll! We probably got " \
+              "the name wrong.", #f);                                   \
+      return -1;                                                        \
+    } else {                                                            \
+      service_fns.f ## _fn = fn;                                        \
+    }                                                                   \
+  } while (0)
+
+  LOAD(ChangeServiceConfig2);
+  LOAD(CloseServiceHandle);
+  LOAD(ControlService);
+  LOAD(CreateService);
+  LOAD(DeleteService);
+  LOAD(OpenSCManager);
+  LOAD(OpenService);
+  LOAD(QueryServiceStatus);
+  LOAD(RegisterServiceCtrlHandler);
+  LOAD(SetServiceStatus);
+  LOAD(StartServiceCtrlDispatcher);
+  LOAD(StartService);
+
+  service_fns.loaded = 1;
+
+  return 0;
+}
+
 /** Checks if torrc is present in the same directory
  *  as the service executable.
  *  Return 1 if it is, 0 if it is not present. */
@@ -1704,10 +1815,13 @@
 static int
 nt_service_is_stopped(void)
 {
+  if (nt_service_loadlibrary()<0)
+    return -1;
+
   if (service_status.dwCurrentState == SERVICE_STOP_PENDING) {
     service_status.dwWin32ExitCode = 0;
     service_status.dwCurrentState = SERVICE_STOPPED;
-    SetServiceStatus(hStatus, &service_status);
+    service_fns.SetServiceStatus_fn(hStatus, &service_status);
     return 1;
   } else if (service_status.dwCurrentState == SERVICE_STOPPED) {
     return 1;
@@ -1723,6 +1837,9 @@
   exit_now.tv_sec  = 0;
   exit_now.tv_usec = 0;
 
+  if (nt_service_loadlibrary()<0)
+    return;
+
   switch (request) {
     case SERVICE_CONTROL_STOP:
         case SERVICE_CONTROL_SHUTDOWN:
@@ -1732,7 +1849,7 @@
           event_loopexit(&exit_now);
           return;
   }
-  SetServiceStatus(hStatus, &service_status);
+  service_fns.SetServiceStatus_fn(hStatus, &service_status);
 }
 
 /** DOCDOC */
@@ -1740,6 +1857,8 @@
 nt_service_body(int argc, char **argv)
 {
   int r;
+  if (nt_service_loadlibrary()<0)
+    return;
   service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
   service_status.dwCurrentState = SERVICE_START_PENDING;
   service_status.dwControlsAccepted =
@@ -1748,7 +1867,7 @@
   service_status.dwServiceSpecificExitCode = 0;
   service_status.dwCheckPoint = 0;
   service_status.dwWaitHint = 1000;
-  hStatus = RegisterServiceCtrlHandler(GENSRV_SERVICENAME,
+  hStatus = service_fns.RegisterServiceCtrlHandler_fn(GENSRV_SERVICENAME,
                                    (LPHANDLER_FUNCTION) nt_service_control);
 
   if (hStatus == 0) {
@@ -1775,11 +1894,11 @@
     service_status.dwCurrentState = SERVICE_STOPPED;
     service_status.dwWin32ExitCode = r;
     service_status.dwServiceSpecificExitCode = r;
-    SetServiceStatus(hStatus, &service_status);
+    service_fns.SetServiceStatus_fn(hStatus, &service_status);
     return;
   }
   service_status.dwCurrentState = SERVICE_RUNNING;
-  SetServiceStatus(hStatus, &service_status);
+  service_fns.SetServiceStatus_fn(hStatus, &service_status);
   do_main_loop();
   tor_cleanup();
   return;
@@ -1792,12 +1911,14 @@
   SERVICE_TABLE_ENTRY table[2];
   DWORD result = 0;
   char *errmsg;
+  if (nt_service_loadlibrary()<0)
+    return;
   table[0].lpServiceName = GENSRV_SERVICENAME;
   table[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)nt_service_body;
   table[1].lpServiceName = NULL;
   table[1].lpServiceProc = NULL;
 
-  if (!StartServiceCtrlDispatcher(table)) {
+  if (!service_fns.StartServiceCtrlDispatcher_fn(table)) {
     result = GetLastError();
     errmsg = nt_strerror(result);
     printf("Service error %d : %s\n", (int) result, errmsg);
@@ -1833,9 +1954,10 @@
 {
   SC_HANDLE hSCManager;
   char *errmsg = NULL;
-
-  if ((hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE))
-      == NULL) {
+  if (nt_service_loadlibrary()<0)
+    return 0;
+  if ((hSCManager = service_fns.OpenSCManager_fn(
+                            NULL, NULL, SC_MANAGER_CREATE_SERVICE)) == NULL) {
     errmsg = nt_strerror(GetLastError());
     printf("OpenSCManager() failed : %s\n", errmsg);
     LocalFree(errmsg);
@@ -1850,7 +1972,9 @@
   SC_HANDLE hService;
   char *errmsg = NULL;
 
-  if ((hService = OpenService(hSCManager, GENSRV_SERVICENAME,
+  if (nt_service_loadlibrary()<0)
+    return 0;
+  if ((hService = service_fns.OpenService_fn(hSCManager, GENSRV_SERVICENAME,
                               SERVICE_ALL_ACCESS)) == NULL) {
     errmsg = nt_strerror(GetLastError());
     printf("OpenService() failed : %s\n", errmsg);
@@ -1865,15 +1989,18 @@
 {
   char *errmsg = NULL;
 
-  QueryServiceStatus(hService, &service_status);
+  if (nt_service_loadlibrary()<0)
+    return -1;
+
+  service_fns.QueryServiceStatus_fn(hService, &service_status);
   if (service_status.dwCurrentState == SERVICE_RUNNING) {
     printf("Service is already running\n");
     return 1;
   }
 
-  if (StartService(hService, 0, NULL)) {
+  if (service_fns.StartService_fn(hService, 0, NULL)) {
     /* Loop until the service has finished attempting to start */
-    while (QueryServiceStatus(hService, &service_status)) {
+    while (service_fns.QueryServiceStatus_fn(hService, &service_status)) {
       if (service_status.dwCurrentState == SERVICE_START_PENDING)
         Sleep(500);
       else
@@ -1904,15 +2031,18 @@
 nt_service_stop(SC_HANDLE hService)
 {
   char *errmsg = NULL;
+  if (nt_service_loadlibrary()<0)
+    return -1;
 
-  QueryServiceStatus(hService, &service_status);
+  service_fns.QueryServiceStatus_fn(hService, &service_status);
   if (service_status.dwCurrentState == SERVICE_STOPPED) {
     printf("Service is already stopped\n");
     return 1;
   }
 
-  if (ControlService(hService, SERVICE_CONTROL_STOP, &service_status)) {
-    while (QueryServiceStatus(hService, &service_status)) {
+  if (service_fns.ControlService_fn(hService, SERVICE_CONTROL_STOP,
+                                    &service_status)) {
+    while (service_fns.QueryServiceStatus_fn(hService, &service_status)) {
       if (service_status.dwCurrentState == SERVICE_STOP_PENDING)
         Sleep(500);
       else
@@ -1972,6 +2102,8 @@
   char *errmsg;
   int len = 0;
 
+  if (nt_service_loadlibrary()<0)
+    return -1;
   if (0 == GetModuleFileName(NULL, szPath, MAX_PATH))
     return 0;
 
@@ -2002,7 +2134,7 @@
    * - and changed the lpPassword param to "" instead of NULL as per an
    *   MSDN article.
    */
-  if ((hService = CreateService(hSCManager, GENSRV_SERVICENAME,
+  if ((hService = service_fns.CreateService_fn(hSCManager, GENSRV_SERVICENAME,
                                 GENSRV_DISPLAYNAME,
                                 SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
                                 SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
@@ -2010,7 +2142,7 @@
                                 NULL, NULL, NULL, NULL, "")) == NULL) {
     errmsg = nt_strerror(GetLastError());
     printf("CreateService() failed : %s\n", errmsg);
-    CloseServiceHandle(hSCManager);
+    service_fns.CloseServiceHandle_fn(hSCManager);
     LocalFree(errmsg);
     tor_free(command);
     return 0;
@@ -2018,14 +2150,15 @@
 
   /* Set the service's description */
   sdBuff.lpDescription = GENSRV_DESCRIPTION;
-  ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sdBuff);
+  service_fns.ChangeServiceConfig2_fn(hService, SERVICE_CONFIG_DESCRIPTION,
+                                      &sdBuff);
   printf("Service installed successfully\n");
 
   /* Start the service initially */
   nt_service_start(hService);
 
-  CloseServiceHandle(hService);
-  CloseServiceHandle(hSCManager);
+  service_fns.CloseServiceHandle_fn(hService);
+  service_fns.CloseServiceHandle_fn(hSCManager);
   tor_free(command);
 
   return 0;
@@ -2039,17 +2172,20 @@
   SC_HANDLE hService = NULL;
   char *errmsg;
 
+  if (nt_service_loadlibrary()<0)
+    return -1;
+
   if ((hSCManager = nt_service_open_scm()) == NULL) {
     return 0;
   }
 
   if ((hService = nt_service_open(hSCManager)) == NULL) {
-    CloseServiceHandle(hSCManager);
+    service_fns.CloseServiceHandle_fn(hSCManager);
     return 0;
   }
 
   if (nt_service_stop(hService)) {
-    if (DeleteService(hService)) {
+    if (service_fns.DeleteService_fn(hService)) {
       printf("Removed service successfully\n");
     }
     else {
@@ -2062,8 +2198,8 @@
     printf("Service could not be removed\n");
   }
 
-  CloseServiceHandle(hService);
-  CloseServiceHandle(hSCManager);
+  service_fns.CloseServiceHandle_fn(hService);
+  service_fns.CloseServiceHandle_fn(hSCManager);
 
   return 0;
 }
@@ -2151,6 +2287,10 @@
   backup_argc = argc;
   if ((argc >= 3) &&
       (!strcmp(argv[1], "-service") || !strcmp(argv[1], "--service"))) {
+    if (nt_service_loadlibrary() < 0) {
+      printf("Unable to load library support for NT services.\n");
+      return -1;
+    }
     if (!strcmp(argv[2], "install"))
       return nt_service_install();
     if (!strcmp(argv[2], "remove"))
@@ -2164,6 +2304,10 @@
   }
   // These are left so as not to confuse people who are used to these options
   if (argc >= 2) {
+    if (nt_service_loadlibrary() < 0) {
+      printf("Unable to load library support for NT services.\n");
+      return -1;
+    }
     if (!strcmp(argv[1], "-install") || !strcmp(argv[1], "--install"))
       return nt_service_install();
     if (!strcmp(argv[1], "-remove") || !strcmp(argv[1], "--remove"))