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
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
-
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
- 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; }
- 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"); }
- 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; }
- 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 }
- 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; }
- & 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; }
- 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); }
- 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
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.
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here