How do I return an error from the service?

I am writing a service application that sometimes cannot be stopped immediately after receiving SERVICE_CONTROL_STOP from the MMC services. I currently handle it like this: (in pseudocode):

DWORD 
HandlerEx(
    DWORD dwControl, 
    DWORD dwEventType, 
    PVOID pvEventData, 
    PVOID pvContext
) 
{
    switch( dwControl )
    {
    case SERVICE_CONTROL_STOP:
        if ( CanStopServiceNow() )
        {
             ReportStatus( SERVICE_STOP_PENDING );
             DoStopService();
             ReportStatus( SERVICE_STOPPED );
             return NO_ERROR;
        }
        else
             return ERROR_BUSY;
        break;
    }

    return NO_ERROR;
}

      

This works well when the service can stop (and it stops), but when it cannot stop, I expect Windows to report the error I am returning (ERROR_BUSY in this example.) Instead, Windows displays a message saying

"The service did not return an error. 
This could be an internal Windows error or an internal service error." 

      

So my question is, how do I get the service report back to the SCM that it can't stop now and get the MMC to display the actual error code I'm returning?

+1


source to share


2 answers


I know this will not answer your specific question. But, as it seems to me, the answer is: "There is no way." I'll make an offer anyway. For most applications that need more control over how they start and stop, I can think of Sap and Oracle, use a Windows service as an administrative service, and implement a gui or command line interface to start and stop the actual "workflow".



+1


source


Answering my own question (after examining the problem in more detail): instead of returning an error code from the HandlerEx function, the service should report its status to the SCM, indicating whether it can accept a SERVICE_CONTROL_STOP code. If a service detects that it cannot be stopped immediately, it should clear the SERVICE_ACCEPT_STOP bit in its SERVICE_STATUS structure and call SetServiceStatus (). This should prevent SCM from trying to stop the service in the first place. When the condition clears and the service decides it is safe, it should set the SERVICE_ACCEPT_STOP bit and call SetServiceStatus () again.



+1


source







All Articles