Details

    • Sub-task
    • Resolution: Fixed
    • Major
    • 0.4.9
    • Services
    • None

    Description

      When a service control application sends a ControlService(SERVICE_CONTROL_STOP) to the Services Control Manager (SCM) to stop a given service, the SCM (via the ScmControlService sub-call) MUST NOT immediately dereference (and possibly kill) the service image, and the client-side (advapi32, ScServiceDispatcher) MUST NOT immediately terminate the dispatcher loop, possibly terminating StartServiceCtrlDispatcher if dwRunningServices becomes == 0.
      The overall bad effects caused by this is that the service becomes unable to report its SERVICE_STOP_PENDING status back to the SCM, using SetServiceStatus calls, since its service status handle becomes invalid (SetServiceStatus would return an ERROR_INVALID_HANDLE error code), and therefore, all the applications that rely on the following programming pattern (errors checking omitted for simplicity) (see also this example from MSDN) would fail:

      /* Stop the service */
      ControlService(hService, SERVICE_CONTROL_STOP);
       
      /* Monitor stopping progression, possibly showing a progress bar */
      while (Status.dwCurrentState != SERVICE_STOPPED)
      {
          QueryServiceStatus(hService, &Status);
          if (Status.dwCurrentState == SERVICE_STOPPED)
              break;
          /* Do some other actions */
          Sleep(1000); // Sleep a little
      }
       
      /* Yeah, service stopped 8^) */

      This is in particular the case of the MSI action "CAInitSPPTokenStore.x86" in the Word 2010 installer, which stops & restarts the OSPPSVC service, and which otherwise fails if either one of the calls shown in the previous code snippet fails.

      Furthermore, according to the MSDN article "Writing a Service Program's main Function" and my own tracing / step-tracing inside Win2k3, the "[dispatcher] thread returns when there is an error or when all of the services in the process have terminated. When all services in the process have terminated, the SCM sends a control request to the dispatcher thread telling it to exit. This thread then returns from the StartServiceCtrlDispatcher call and the process can terminate."
      While we attempt to do the first action described there, we do not perform the second one (SCM sending a stop control for the dispatcher itself).

      Attachments

        Issue Links

          Activity

            People

              ekohl ekohl
              hbelusca hbelusca
              Votes:
              2 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: