Fixed permissions check in open_registry().
[nssm.git] / service.cpp
index 0a8773a..5a28641 100644 (file)
@@ -38,6 +38,7 @@ static inline int service_control_response(unsigned long control, unsigned long
     case SERVICE_CONTROL_STOP:\r
     case SERVICE_CONTROL_SHUTDOWN:\r
       switch (status) {\r
+        case SERVICE_RUNNING:\r
         case SERVICE_STOP_PENDING:\r
           return 1;\r
 \r
@@ -73,6 +74,7 @@ static inline int service_control_response(unsigned long control, unsigned long
       }\r
 \r
     case SERVICE_CONTROL_INTERROGATE:\r
+    case NSSM_SERVICE_CONTROL_ROTATE:\r
       return 0;\r
   }\r
 \r
@@ -81,12 +83,17 @@ static inline int service_control_response(unsigned long control, unsigned long
 \r
 static inline int await_service_control_response(unsigned long control, SC_HANDLE service_handle, SERVICE_STATUS *service_status, unsigned long initial_status) {\r
   int tries = 0;\r
+  unsigned long checkpoint = 0;\r
+  unsigned long waithint = 0;\r
   while (QueryServiceStatus(service_handle, service_status)) {\r
     int response = service_control_response(control, service_status->dwCurrentState);\r
     /* Alas we can't WaitForSingleObject() on an SC_HANDLE. */\r
     if (! response) return response;\r
     if (response > 0 || service_status->dwCurrentState == initial_status) {\r
-      if (++tries > 10) return response;\r
+      if (service_status->dwCheckPoint != checkpoint || service_status->dwWaitHint != waithint) tries = 0;\r
+      checkpoint = service_status->dwCheckPoint;\r
+      waithint = service_status->dwWaitHint;\r
+      if (++tries > 10) tries = 10;\r
       Sleep(50 * tries);\r
     }\r
     else return response;\r
@@ -1363,7 +1370,7 @@ void WINAPI service_main(unsigned long argc, TCHAR **argv) {
   /* Initialise status */\r
   ZeroMemory(&service->status, sizeof(service->status));\r
   service->status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;\r
-  service->status.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;\r
+  service->status.dwControlsAccepted = 0;\r
   service->status.dwWin32ExitCode = NO_ERROR;\r
   service->status.dwServiceSpecificExitCode = 0;\r
   service->status.dwCheckPoint = 0;\r
@@ -1689,10 +1696,12 @@ int start_service(nssm_service_t *service) {
     so abandon the wait before too much time has elapsed.\r
   */\r
   service->status.dwCurrentState = SERVICE_START_PENDING;\r
+  service->status.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;\r
   if (await_single_handle(service->status_handle, &service->status, service->process_handle, service->name, _T("start_service"), service->throttle_delay) == 1) service->throttle = 0;\r
 \r
   /* Signal successful start */\r
   service->status.dwCurrentState = SERVICE_RUNNING;\r
+  service->status.dwControlsAccepted &= ~SERVICE_ACCEPT_PAUSE_CONTINUE;\r
   SetServiceStatus(service->status_handle, &service->status);\r
 \r
   /* Continue waiting for a clean startup. */\r
@@ -1728,8 +1737,9 @@ int stop_service(nssm_service_t *service, unsigned long exitcode, bool graceful,
   if (graceful) {\r
     service->status.dwCurrentState = SERVICE_STOP_PENDING;\r
     service->status.dwWaitHint = NSSM_WAITHINT_MARGIN;\r
-    SetServiceStatus(service->status_handle, &service->status);\r
   }\r
+  service->status.dwControlsAccepted = 0;\r
+  SetServiceStatus(service->status_handle, &service->status);\r
 \r
   /* Nothing to do if service isn't running */\r
   if (service->pid) {\r
@@ -1887,6 +1897,7 @@ void throttle_restart(nssm_service_t *service) {
   }\r
 \r
   service->status.dwCurrentState = SERVICE_PAUSED;\r
+  service->status.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;\r
   SetServiceStatus(service->status_handle, &service->status);\r
 \r
   if (use_critical_section) {\r