Click here to Skip to main content
15,884,425 members
Articles / Desktop Programming / MFC
Article

MFS Service Manger

Rate me:
Please Sign up or sign in to vote.
3.73/5 (20 votes)
8 Dec 2004CPOL4 min read 82.5K   2.5K   55   14
A fully functional replica of Windows Service Manager, with some extra features like Enumeration, Deletion and Updation of the Services.

Sample Application

Introduction

Hello fellow CPians,

Back again with new application .I think, you wanna know that what exactly this application is doing. This application can enumerate all window services, provide support for Starting, Stopping and Restarting, provide support for switching the Startup Type between Automatic, Manual And Disable, changing the path of Services and last but not the least and most dangerous one Uninstalling the Service.

"I Request, Please handle this Option with Care (UnInstalling One), if this action is executed once, there is no chance of rollback or you know how to install that particular service".

Background

Now let's take a look at what MSDN says about services ---

“A service application conforms to the interface rules of the Service Control Manager (SCM). It can be started automatically at system boot, by a user through the Services control panel applet, or by an application that uses the service functions, Services Start Running.

A driver service conforms to the device driver protocols. It is similar to a service application, but it does not interact with the SCM. For simplicity, the term service refers to a service application in this overview. "

This is the list of all the APIs I have used to Enumerate, Control, Edit and Delete service.

A Little Description About These APIs

  • OpenSCManager

      SC_HANDLE OpenSCManager
      (
         LPCTSTR lpMachineName,   // computer name
         LPCTSTR lpDatabaseName,  // SCM database name
         DWORD dwDesiredAccess    // access type 
      );

    A little description about OpenSCManager

    This API is used to open the database of service on local computer. Yeah, you can open it to use the service database on remote computer (but that required proper network authorization). You need to open the service manager to perform each service related task.

  • OpenService

    SC_HANDLE OpenService
    (
       SC_HANDLE hSCManager,  // handle to SCM database
       LPCTSTR lpServiceName, // service name
       DWORD dwDesiredAccess  // access
    );
    

    A little description about OpenService

    This API is used to open particular service from service database. This API is used after a successful call of OpenSCManager API.

  • EnumServiceStatus

    BOOL EnumServicesStatus
    (
      SC_HANDLE hSCManager,             // handle to SCM database
      DWORD dwServiceType,              // service type
      DWORD dwServiceState,             // service state
      LPENUM_SERVICE_STATUS lpServices, // status buffer
      DWORD cbBufSize,                  // size of status buffer
      LPDWORD pcbBytesNeeded,           // buffer size needed
      LPDWORD lpServicesReturned,       // number of entries returned
      LPDWORD lpResumeHandle            // next entry
    );
    

    A little description about EnumServiceStatus

    As the name indicates, this API is used to enumerate the services depending upon function call specifications:

    • Second parameter - which type of service you want to enumerate.
    • Third parameter - what type of service is returned, i.e. running or stopped services.
    • Fourth parameter - buffer of ENUM_SERVICE_STATUS ( which will bring back all the Services).
    • Fifth parameter - will hold total buffer size of fourth parameter
    • Sixth parameter - contain total byte of memory needed to retrieve all the service with necessary details (i.e. ENUM_SERVICE_STATUS)
    • Seventh parameter - contains number of services returned after successful call of above API.
    • Eighth parameter - is returned with resume handle if the buffer is not enough to hold the all the services present in system.
  • QueryServiceConfig

    BOOL QueryServiceConfig
    (
      SC_HANDLE hService,                     // handle to service
      LPQUERY_SERVICE_CONFIG lpServiceConfig, // buffer
      DWORD cbBufSize,                        // size of buffer
      LPDWORD pcbBytesNeeded                  // bytes needed
    );

    A little description about QueryServieConfig

    This API query current status of service, where the first parameter is handle obtained from OpenService and the second parameter is structure, which will return with information.

  • StartService

    BOOL StartService
    (
      SC_HANDLE hService,            // handle to service
      DWORD dwNumServiceArgs,        // number of arguments
      LPCTSTR* lpServiceArgVectors   // array of arguments
    );

    A little description about StartService

    As the name suggests that it will Start service whose handle is going to pass in the first parameter, second parameter inputs the number of arguments for service to be passed in parameter three and third parameter is an array of string argument for service.

  • ControlService

    BOOL ControlService
    (
      SC_HANDLE hService,               // handle to service
      DWORD dwControl,                  // control code
      LPSERVICE_STATUS lpServiceStatus  // status information
    );

    A little description about ControlService

    As the name suggests that it will Control service whose handle is going to pass in the First Parameter, Second Parameter specifies the requested control code, most common are SERVICE_CONTROL_STOP, SERVICE_CONTROL_PAUSE, SERVICE_CONTROL_CONTINUE and third Parameter returns current status structure of service.

  • DeleteService

    BOOL DeleteService
    (
      SC_HANDLE hService   // handle to service
    );

    A little description about DeleteService

    As the name suggests that it will Delete service whose handle is going to be passed in the First Parameter.

  • ChangeServiceConfig

    BOOL ChangeServiceConfig
    (
      SC_HANDLE hService          // handle to service
      DWORD dwServiceType,        // type of service
      DWORD dwStartType,          // when to start service
      DWORD dwErrorControl,       // severity of start failure
      LPCTSTR lpBinaryPathName,   // service binary file name
      LPCTSTR lpLoadOrderGroup,   // load ordering group name
      LPDWORD lpdwTagId,          // tag identifier
      LPCTSTR lpDependencies,     // array of dependency names
      LPCTSTR lpServiceStartName, // account name
      LPCTSTR lpPassword,         // account password
      LPCTSTR lpDisplayName       // display name
    );

    A little description about ChangeServiceConfig

    As name indicates, this API is used to Change the service Configuration. I am going to discuss commonly used parameter of this API.

    • First Parameter - Indicates the handle of service.
    • Second parameter - If you want to change service type.
    • Third parameter - For changing startup type.
    • Fifth Parameter - For changing binary path of executable.
    • Ninth parameter - Indicates in which user, you want to run the service.
    • Tenth parameter - Password of account specified in ninth paragraph.
    • Eleventh Parameter - Used to change the display name of the service.

Using the code

I will Explain Everything now, with the help of code snippet.

Here is list of possible common functions that can be performed from above APIs.

I know more combinations possible, but I am stating those only which is going to provide with MFS Service Manager TM :D

  1. For obtaining the main ScManager handle.
    SC_HANDLE ScManager; 
    //here I am opening the service manager using OpenScManager API call 
    
    ScManager=::OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE|GENERIC_READ); 
    
    //check that whether we able to connect with local computer service 
    //database or Not
    //Remember if we Use SC_MANAGER_ALL_ACCESS, we need Administrator
    //right for that.
    //with using SC_MANAGER_ENUMERATE_SERVICE|GENERIC_READ it guranteed 
    //that it going to open for each user 
            
    if(ScManager==NULL) 
    {
       MessageBox("Error Opening Service Mgr"); 
       return; 
    }
  2. For obtaining particular service handle.
    SC_HANDLE ScService;
    //Open Service
    if((ScService=::OpenService(
         ScManager,"any service Name",SERVICE_ALL_ACCESS))==NULL)
    {
         ::CloseHandle(ScManager);
         MessageBox("Problem in opening service");
    }
  3. For enumerating the service.
    ENUM_SERVICE_STATUS EnService[512]; //service Enumeration Structure
    DWORD cbBufSize=512*sizeof(ENUM_SERVICE_STATUS); // size of status buffer
    DWORD lpServicesReturned; 
    DWORD pcbBytesNeeded; // buffer size needed
    DWORD lpResumeHandle       
    DWORD lpResumeHandle=0; // next entry 
    
    //Assuming that you got the Handle if SCManager from OpenSCManager
    
    if(::EnumServicesStatus(
      ScManager,//Service manager Handle
      SERVICE_WIN32, //Service type To be retrieved
      SERVICE_STATE_ALL, //
      EnService, // Buffer 
      cbBufSize, //Buffer Size
      &pcbBytesNeeded, //number of Bytes Needed
      &lpServicesReturned, //number of Service Return
      &lpResumeHandle //Resume Handle if any
    
      )= =0)
      {
        MessageBox("Error Querrying Service Mgr"); 
        return; 
      }
  4. Checking state of service.
    // now check the state of each service 
    for(int i=0;i< INT ( LPSERVICESRETURNED);i++) 
    {
      MessageBox(EnService[i].lpServiceName,"service Name"); 
      MessageBox(EnService[i].lpDisplayName,"Display Name");
    
    //the ENUM_SERVICE_STATUS third parameter 
    //contain the status of each service 
    
    switch(EnService[i].ServiceStatus.dwCurrentState)
     {
        case SERVICE_PAUSED: //service in paused state
        case SERVICE_RUNNING: // The service is running.
        case SERVICE_STOPPED:// The service is stopped 
        case SERVICE_START_PENDING: // The service is starting 
        case SERVICE_STOP_PENDING : // The service is stopped 
        default: //unknown state
     }
  5. For starting the service.
    //assuming that ScService contain Vaild Handle after 
    //Successful call of OpenService
    
    if(::StartService(ScService,0,NULL)==0) 
    { 
       //preparing Error 
       Variable MessageBox("Error Starting Service"); 
       return; 
    }
  6. & 7. For pausing and stopping service.
    //assuming that ScService contain Vaild Handle after 
    //Successful call of OpenService
    //For Pausing Service pass SERVICE_CONTROL_PAUSE in 
    //Second Parameter 
    if(::ControlService(ScService,SERVICE_CONTROL_STOP,&stt)==0) 
    { 
      //IF Error Occurs 
      MessageBox("Error: Unable to Stop Service"); 
      return; 
    }
  1. Updating the path of service.
    //assuming that ScService contain Vaild Handle after 
    //Successful call of OpenService
    //Here is Code Snipet for getting  Path
    
    LPQUERY_SERVICE_CONFIG lpqscBuf;
    DWORD dwBytesNeeded;
    //Allocate the necessary memory to Query Structure ,so
    // that we can get all the Needed Data without any Buffer Problem
    
    lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc( LPTR,4096);
    
    if (lpqscBuf == NULL)
    {
      MessageBox("Memory Allocation error");
      return;
    }
    
    // Get     theconfiguration information.
    //Call the real function,that will query
    //service for its path etc.
    
     if (!QueryServiceConfig(
         
          
          ScService,
          lpqscBuf,
          4096,
          &dwBytesNeeded)
        )
      {
         MessageBox("Error in querying Services");
         return;
      }
    
    MessageBox(lpqscBuf->lpBinaryPathName ,"Current Binary path");
    
    //Here to Code Snippet for Updating Path
    
    if(::ChangeServiceConfig(
       ScService,
       SERVICE_NO_CHANGE,
       SERVICE_NO_CHANGE,
       SERVICE_NO_CHANGE,
      
      
       NEW PATH,//path to be changed
       NULL,NULL,NULL,NULL,NULL,NULL))
      {
         MessageBox("Service PathChanged",
             "MFS SERVICEMGR",MB_OK|MB_ICONINFORMATION);
      }
      else
      {
         MessageBox("Error In ChangingPath","MFS SERVICE MGR",MB_OK|MB_ICONSTOP);
      }
  2. For deleting the service.
    //assuming that ScService contain Vaild Handle 
    //after Successful call of OpenService
    
    if(::DeleteService(ScService)==0)
    { //Showing Message
      MessageBox("Error Deleting Service");
      return;
    }
    else
    {
       MessageBox("Service Marked For Deletion\nDeleted After Computer Restart");
    }

History

  • Version 1.0

    First Release.

  • Version 1.1

    Updated the binary path option to edit the service executable path as asked by my friend Suhredayan and other bug fixes.

Special Thanks

  • My Parents
  • My friend Amit Mehta
  • Mr. Suhredayan for demanding newer version of this application.
  • The Code Project for providing platform for emerging Programmers.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
He used to have biography here Smile | :) , but now he will hire someone (for free offcourse Big Grin | :-D ), Who writes his biography on his behalf Smile | :)

He is Great Fan of Mr. Johan Rosengren (his idol),Lim Bio Liong, Nishant S and DavidCrow and Believes that, he will EXCEL in his life by following there steps!!!

He started with Visual C++ then moved to C# then he become language agnostic, you give him task,tell him the language or platform, he we start immediately, if he knows the language otherwise he quickly learn it and start contributing productively

Last but not the least, For good 8 years he was Visual CPP MSMVP!

Comments and Discussions

 
Generalmanager service of remote computer Pin
Tailana18-May-05 21:56
Tailana18-May-05 21:56 
GeneralRe: manager service of remote computer Pin
ThatsAlok18-May-05 22:39
ThatsAlok18-May-05 22:39 
Generalservice status notofication Pin
Anonymous8-Feb-05 20:10
Anonymous8-Feb-05 20:10 
How can I get service status notofication in my application?
If I need to monitor a service status, currently a thread in Application should ping it periodically to get current status of serive.
But is there any callback/notification available so that I do not need to ping for status.
GeneralRe: service status notofication Pin
ThatsAlok8-Feb-05 20:52
ThatsAlok8-Feb-05 20:52 
Generalnot so bad, but... Pin
toxcct5-Oct-04 22:52
toxcct5-Oct-04 22:52 
GeneralRe: not so bad, but... Pin
Abu Mami5-Oct-04 23:41
Abu Mami5-Oct-04 23:41 
GeneralRe: not so bad, but... Pin
toxcct6-Oct-04 0:19
toxcct6-Oct-04 0:19 
GeneralGudie Gudie Pin
ThatsAlok6-Oct-04 0:59
ThatsAlok6-Oct-04 0:59 
GeneralRe: Gudie Gudie Pin
toxcct6-Oct-04 1:03
toxcct6-Oct-04 1:03 
GeneralRe: Gudie Gudie Pin
ThatsAlok6-Oct-04 1:30
ThatsAlok6-Oct-04 1:30 
GeneralRe: Gudie Gudie Pin
MGutmann13-Oct-04 20:02
MGutmann13-Oct-04 20:02 
GeneralRe: Gudie Gudie Pin
ThatsAlok14-Oct-04 19:52
ThatsAlok14-Oct-04 19:52 
Generalsmall update request Pin
2249175-Oct-04 0:52
2249175-Oct-04 0:52 
GeneralRe: small update request Pin
ThatsAlok5-Oct-04 18:57
ThatsAlok5-Oct-04 18:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.