Hi,

We've encountered a problem with the way jk_nt_service.c creates nt
services.

Specifically, the call to CreateService uses the name passed in for the
service as both the service name and the service display name.  This is a
problem because there are restrictions on the service name that do not apply
to the display name.  The MS documentation states that neither forward nor
back slashes are allowed but in practice I have found that other characters
cause problems as well.

For example, if you create a service via jk_nt_service -i "My Service"
wrapper.properties the service creates just fine but it fails to start.

Since the MS source is not readily available we can't check on what the REAL
rules are for the internal service name.

To be safe, a solution I have used in the past is to treat the name passed
in via the command line as the display name, and then remove all
non-alphanumeric characters to generate the internal service name.

This is cheap, but might cause trouble if you are unlucky enough to have
multiple service display names mapping to a single internal name as in "My
Service 1.1" and "My Service 11".

An alternative that fixes this is to convert non alphanumerics to their hex
representation.

I've attached a patch using the first approach since I've used in in the
past without any problems.  I'll be happy to rework it to hex encode non
alphanumerics if there is interest.

-David

--- jk_nt_service.c.orig        Sun Oct 21 13:25:54 2001
+++ jk_nt_service.c     Wed Dec 19 17:59:38 2001
@@ -113,16 +113,22 @@
 static void WINAPI service_ctrl(DWORD dwCtrlCode);
 static void WINAPI service_main(DWORD dwArgc,
                                 char **lpszArgv);
+
+static char *sanitize_service_name(char *displayName);
 static void install_service(char *name,
+                           char *dname,
                             char *user,
                             char *password,
                             char *deps,
                             BOOL bAutomatic,
                             char *rel_prp_file);
-static void remove_service(char *name);
+static void remove_service(char *name,
+                          char *dname);
 static void start_service(char *name,
+                         char *dname,
                           char *machine);
 static void stop_service(char *name,
+                        char *dname,
                          char *machine);
 static char *GetLastErrorText(char *lpszBuf, DWORD dwSize);
 static void AddToMessageLog(char *lpszMsg);
@@ -132,6 +138,7 @@
 static void start_jk_service(char *name);
 static void stop_jk_service(void);
 static int set_registry_values(char *name,
+                              char *dname,
                                char *prp_file);
 static int create_registry_key(const char *tag,
                                HKEY *key);
@@ -182,6 +189,7 @@
     int count;
     int iAction = acNoAction;
     char *pServiceName = NULL;
+    char *pServiceDisplayName = NULL;
     char *pUserName = NULL;
     char *pPassword = NULL;
     char *pMachine = NULL;
@@ -219,16 +227,16 @@
                     cmd++;
                     if(0 == stricmp("i", cmd)) {
                         iAction = acInstall;
-                        pServiceName = argv[i+1];
+                        pServiceDisplayName = argv[i+1];
                     } else if(0 == stricmp("r", cmd)) {
                         iAction = acRemove;
-                        pServiceName = argv[i+1];
+                        pServiceDisplayName = argv[i+1];
                     } else if(0 == stricmp("s", cmd)) {
                         iAction = acStartTC;
-                        pServiceName = argv[i+1];
+                        pServiceDisplayName = argv[i+1];
                     } else if(0 == stricmp("t", cmd)) {
                         iAction = acStopTC;
-                        pServiceName = argv[i+1];
+                        pServiceDisplayName = argv[i+1];
                     } else if(0 == stricmp("u", cmd)) {
                         pUserName = argv[i+1];
                     } else if(0 == stricmp("p", cmd)) {
@@ -243,18 +251,19 @@
                     }
                 }
             }
+           pServiceName = sanitize_service_name(pServiceDisplayName);
             switch (iAction) {
             case acInstall:
-                install_service(pServiceName, pUserName, pPassword, strDependancy, 
bAutomatic, argv[i-1]);
+                install_service(pServiceName, pServiceDisplayName, pUserName, 
+pPassword, strDependancy, bAutomatic, argv[i-1]);
                 return;
             case acRemove:
-                remove_service(pServiceName);
+                remove_service(pServiceName, pServiceDisplayName);
                 return;
             case acStartTC:
-                start_service(pServiceName, pMachine);
+                start_service(pServiceName, pServiceDisplayName, pMachine);
                 return;
             case acStopTC:
-                stop_service(pServiceName, pMachine);
+                stop_service(pServiceName, pServiceDisplayName, pMachine);
                 return;
             }
         } else if(2  == argc) {
@@ -274,6 +283,9 @@
         usage_message(argv[0]);
         exit(-1);
     } __finally {
+        if (pServiceDisplayName) {
+           free(pServiceDisplayName);
+        }
         WSACleanup();
     }
 }
@@ -374,7 +386,31 @@
     return fResult;
 }
 
+/*
+   Remove non alphanumerics for use as internal service id.
+   MS docs stipulate not to use forward or back slashes but
+   spaces also cause trouble.  Specifically, the service fails
+   to start.  It seems safest to remove all special chars.
+
+   returned pointer should be freed by the caller.
+*/
+char *sanitize_service_name(char *displayName) {
+    char *clean = strdup(displayName);
+    char *ptr = clean;
+
+    while(*displayName) {
+      if (isalnum(*displayName)) {
+          *ptr++ = *displayName;
+      }
+      displayName++;
+    }
+    *ptr = '\0';
+
+    return clean;
+}
+
 void install_service(char *name, 
+                    char *dname,
                      char *user,
                      char *password,
                      char *deps,
@@ -415,9 +451,10 @@
                                  NULL,     // database (NULL == default)
                                  SC_MANAGER_ALL_ACCESS);   // access required
     if(schSCManager) {
+
         schService = CreateService(schSCManager, // SCManager database
-                                   name,         // name of service
-                                   name,         // name to display
+                                   name,          // name of service
+                                   dname,         // name to display
                                    SERVICE_ALL_ACCESS, // desired access
                                    SERVICE_WIN32_OWN_PROCESS,  // service type
                                    bAutomatic ? SERVICE_AUTO_START : 
SERVICE_DEMAND_START,       // start type
@@ -430,9 +467,9 @@
                                    password);                  // password
 
         if(schService) {
-            printf("The service named %s was created. Now adding registry entries\n", 
name);
+            printf("The service named %s was created. Now adding registry entries\n", 
+dname);
             
-            if(set_registry_values(name, szPropPath)) {
+            if(set_registry_values(name, dname, szPropPath)) {
                 CloseServiceHandle(schService);
             } else {
                 printf("CreateService failed setting the private registry - %s\n", 
GetLastErrorText(szErr, sizeof(szErr)));
@@ -447,9 +484,10 @@
     } else { 
         printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
     }
+
 }
 
-void remove_service(char *name)
+void remove_service(char *name, char *dname)
 {
     SC_HANDLE   schService;
     SC_HANDLE   schSCManager;
@@ -464,7 +502,7 @@
         if(schService) {
             // try to stop the service
             if(ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) {
-                printf("Stopping %s.", name);
+                printf("Stopping %s.", dname);
                 Sleep(1000);
 
                 while(QueryServiceStatus(schService, &ssStatus )) {
@@ -477,15 +515,15 @@
                 }
 
                 if(ssStatus.dwCurrentState == SERVICE_STOPPED) {
-                    printf("\n%s stopped.\n", name);
+                    printf("\n%s stopped.\n", dname);
                 } else {
-                    printf("\n%s failed to stop.\n", name);
+                    printf("\n%s failed to stop.\n", dname);
                 }
             }
 
             // now remove the service
             if(DeleteService(schService)) {
-                printf("%s removed.\n", name);
+                printf("%s removed.\n", dname);
             } else {
                 printf("DeleteService failed - %s\n", GetLastErrorText(szErr, 
sizeof(szErr)));
             }
@@ -501,7 +539,7 @@
     }
 }
 
-void start_service(char *name, char *machine)
+void start_service(char *name, char *dname, char *machine)
 {
     SC_HANDLE   schService;
     SC_HANDLE   schSCManager;
@@ -516,7 +554,7 @@
         if(schService) {
             // try to start the service
             if(StartService(schService, 0, NULL)) {
-                printf("Starting %s.", name);
+                printf("Starting %s.", dname);
                 Sleep(1000);
 
                 while(QueryServiceStatus(schService, &ssStatus )) {
@@ -529,9 +567,9 @@
                 }
 
                 if(ssStatus.dwCurrentState == SERVICE_RUNNING) {
-                    printf("\n%s started.\n", name);
+                    printf("\n%s started.\n", dname);
                 } else {
-                    printf("\n%s failed to start.\n", name);
+                    printf("\n%s failed to start.\n", dname);
                 }
             }
             else
@@ -548,7 +586,7 @@
     }
 }
 
-void stop_service(char *name, char *machine)
+void stop_service(char *name, char *dname, char *machine)
 {
     SC_HANDLE   schService;
     SC_HANDLE   schSCManager;
@@ -563,7 +601,7 @@
         if(schService) {
             // try to stop the service
             if(ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) {
-                printf("Stopping %s.", name);
+                printf("Stopping %s.", dname);
                 Sleep(1000);
 
                 while(QueryServiceStatus(schService, &ssStatus )) {
@@ -576,9 +614,9 @@
                 }
 
                 if(ssStatus.dwCurrentState == SERVICE_STOPPED) {
-                    printf("\n%s stopped.\n", name);
+                    printf("\n%s stopped.\n", dname);
                 } else {
-                    printf("\n%s failed to stop.\n", name);
+                    printf("\n%s failed to stop.\n", dname);
                 }
             }
             else
@@ -596,6 +634,7 @@
 }
 
 static int set_registry_values(char *name, 
+                              char *dname,
                                char *prp_file)
 {
     char  tag[1024];
@@ -649,8 +688,8 @@
                 if(rc) {
                     printf("Registry values were added\n");
                     printf("If you have already updated wrapper.properties you may 
start the %s service by executing \"jk_nt_service -s %s\" from the command prompt\n",
-                           name,
-                           name);                    
+                           dname,
+                           dname);                    
                 }
             }
             RegCloseKey(hk);

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to