Windows Services Programming 16

 

 

 

 

 

Stopping a Windows Service Example

 

A service control program can stop a service by using the ControlService() function to send a SERVICE_CONTROL_STOP request. If the service control manager (SCM) receives a SERVICE_CONTROL_STOP request for a service, it instructs the service to stop by forwarding the request to the service's ServiceMain function. However, if the SCM determines that other running services are dependent on the specified service, it will not forward the stop request. Instead, it returns ERROR_DEPENDENT_SERVICES_RUNNING. Therefore, to programmatically stop such a service, you must first enumerate and stop its dependent services. The DoStopSvc() function in the following code fragment example shows how to stop a service and any dependent services. The szSvcName variable is a global variable that contains the name of the service to be stopped.

 

// Purpose: Stops the service

// Parameters: None

// Return value: None

void __stdcall DoStopSvc(void)

{

    SERVICE_STATUS_PROCESS ssp;

    DWORD dwStartTime = GetTickCount();

    DWORD dwBytesNeeded;

    DWORD dwTimeout = 30000; // 30-second time-out

    DWORD dwWaitTime;

 

    // Get a handle to the SCM database

    schSCManager = OpenSCManager(

        NULL,                    // local computer

        NULL,                    // ServicesActive database

        SC_MANAGER_ALL_ACCESS);  // full access rights

 

    if (schSCManager == NULL)

    {

        wprintf(L"OpenSCManager() failed, error %u\n", GetLastError());

        return;

    }

      else

            wprintf(L"OpenSCManager() is pretty working!\n");

 

    // Get a handle to the service

    schService = OpenService(

        schSCManager,         // SCM database

        szSvcName,            // name of service

        SERVICE_STOP |

        SERVICE_QUERY_STATUS |

        SERVICE_ENUMERATE_DEPENDENTS);

 

    if(schService == NULL)

    {

        wprintf(L"OpenService() failed, error %u\n", GetLastError());

        CloseServiceHandle(schSCManager);

        return;

    }

      else

            wprintf(L"OpenService() is fine!\n");

 

    // Make sure the service is not already stopped.

    if (!QueryServiceStatusEx(schService,SC_STATUS_PROCESS_INFO,(LPBYTE)&ssp,sizeof(SERVICE_STATUS_PROCESS),  &dwBytesNeeded))

    {

        wprintf(L"QueryServiceStatusEx() failed, error %u\n", GetLastError());

        goto stop_cleanup;

    }

      else

            wprintf(L"QueryServiceStatusEx() is working!\n");

 

    if (ssp.dwCurrentState == SERVICE_STOPPED)

    {

        wprintf(L"Service is already stopped.\n");

        goto stop_cleanup;

    }

 

    // If a stop is pending, wait for it.

    while (ssp.dwCurrentState == SERVICE_STOP_PENDING)

    {

        wprintf(L"Service stop pending...\n");

 

        // Do not wait longer than the wait hint. A good interval is

        // one-tenth of the wait hint but not less than 1 second 

        // and not more than 10 seconds.

        dwWaitTime = ssp.dwWaitHint / 10;

 

        if( dwWaitTime < 1000 )

            dwWaitTime = 1000;

        else if ( dwWaitTime > 10000 )

            dwWaitTime = 10000;

 

        Sleep(dwWaitTime);

 

        if (!QueryServiceStatusEx(schService,SC_STATUS_PROCESS_INFO,(LPBYTE)&ssp,sizeof(SERVICE_STATUS_PROCESS),  &dwBytesNeeded))

        {

            wprintf(L"QueryServiceStatusEx() failed, error %u\n", GetLastError());

            goto stop_cleanup;

        }

            else

                  wprintf(L"QueryServiceStatusEx() is OK!\n");

 

        if (ssp.dwCurrentState == SERVICE_STOPPED)

        {

            wprintf(L"Service stopped successfully.\n");

            goto stop_cleanup;

        }

 

        if (GetTickCount() - dwStartTime > dwTimeout)

        {

            wprintf(L"Service stop timed out.\n");

            goto stop_cleanup;

        }

    }

 

    // If the service is running, dependencies must be stopped first.

    StopDependentServices();

 

    // Send a stop code to the service.

    if (!ControlService(schService,SERVICE_CONTROL_STOP,(LPSERVICE_STATUS)&ssp))

    {

        wprintf(L"ControlService() failed, error %u\n", GetLastError());

        goto stop_cleanup;

    }

      else

            wprintf(L"ControlService() is OK!\n");

 

    // Wait for the service to stop.

    while (ssp.dwCurrentState != SERVICE_STOPPED)

    {

        Sleep(ssp.dwWaitHint);

        if (!QueryServiceStatusEx(schService,SC_STATUS_PROCESS_INFO,(LPBYTE)&ssp,sizeof(SERVICE_STATUS_PROCESS),  &dwBytesNeeded))

        {

            wprintf(L"QueryServiceStatusEx() failed, error %u\n", GetLastError());

            goto stop_cleanup;

        }

            else

                  wprintf(L"QueryServiceStatusEx() is OK!\n");

 

        if (ssp.dwCurrentState == SERVICE_STOPPED)

            break;

 

        if (GetTickCount() - dwStartTime > dwTimeout)

        {

            wprintf(L"Wait timed out\n");

            goto stop_cleanup;

        }

    }

    wprintf(L"Service stopped successfully\n");

 

stop_cleanup:

    CloseServiceHandle(schService);

    CloseServiceHandle(schSCManager);

}

 

BOOL __stdcall StopDependentServices(void)

{

    DWORD i;

    DWORD dwBytesNeeded;

    DWORD dwCount;

 

    LPENUM_SERVICE_STATUS   lpDependencies = NULL;

    ENUM_SERVICE_STATUS     ess;

    SC_HANDLE               hDepService;

    SERVICE_STATUS_PROCESS  ssp;

 

    DWORD dwStartTime = GetTickCount();

    DWORD dwTimeout = 30000; // 30-second time-out

 

    // Pass a zero-length buffer to get the required buffer size.

    if (EnumDependentServices(schService, SERVICE_ACTIVE,lpDependencies, 0, &dwBytesNeeded, &dwCount))

    {

         // If the Enum call succeeds, then there are no dependent services, so do nothing.

         return TRUE;

    }

    else

    {

        if (GetLastError() != ERROR_MORE_DATA)

            return FALSE; // Unexpected error

 

        // Allocate a buffer for the dependencies.

        lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);

 

        if (!lpDependencies)

            return FALSE;

 

        __try {

            // Enumerate the dependencies.

            if (!EnumDependentServices( schService, SERVICE_ACTIVE,lpDependencies, dwBytesNeeded, &dwBytesNeeded,&dwCount))

            return FALSE;

 

            for (i = 0; i < dwCount; i++)

            {

                ess = *(lpDependencies + i);

                // Open the service.

                hDepService = OpenService(schSCManager,ess.lpServiceName,SERVICE_STOP | SERVICE_QUERY_STATUS);

 

                if (!hDepService)

                   return FALSE;

 

                __try{

                    // Send a stop code.

                    if (!ControlService( hDepService,SERVICE_CONTROL_STOP,(LPSERVICE_STATUS) &ssp))

                    return FALSE;

 

                    // Wait for the service to stop.

                    while (ssp.dwCurrentState != SERVICE_STOPPED)

                    {

                        Sleep(ssp.dwWaitHint);

                        if (!QueryServiceStatusEx(hDepService,SC_STATUS_PROCESS_INFO,(LPBYTE)&ssp,sizeof(SERVICE_STATUS_PROCESS),  &dwBytesNeeded))

                        return FALSE;

 

                        if (ssp.dwCurrentState == SERVICE_STOPPED)

                            break;

 

                        if (GetTickCount() - dwStartTime > dwTimeout)

                            return FALSE;

                    }

                }

                __finally

                {

                    // Always release the service handle.

                    CloseServiceHandle(hDepService);

                }

            }

        }

        __finally

        {

            // Always free the enumeration buffer.

            HeapFree(GetProcessHeap(), 0, lpDependencies);

        }

    }

    return TRUE;

}

 

 

 

 

< Windows Services 15 | Win32 Programming | Windows Services Win32 Programming | Windows Services 17 >