My Project:Service Manager

Discussion in 'Win32' started by alok, Sep 27, 2004.

?

Do u like The Application

  1. Yes

    100.0%
  2. NO

    0 vote(s)
    0.0%
  3. SomeWhat

    11.1%
Multiple votes are allowed.
  1. alok

    alok New Member

    Joined:
    Jul 24, 2004
    Messages:
    127
    Likes Received:
    2
    Trophy Points:
    0
    Occupation:
    S/W Engg
    Home Page:
    http://www.thatsalok.com
    Hello Guys, Back again with new Article. this time I am going to explain Enumeration of Windows service, it’s Starting & Stopping , Changing Startup Type between Automatic, Manual And Disable, And Most Important One Deleting the Service(Please handle this Option With Care, if this action is executed once ,there is no chance of rollback).

    I think every body knows what are Windows services, if not, let me explain it in brief,
    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 can execute even when no user is logged on to the system.

    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. ​

    Explanation



    Now Let Me Explain Two Main Api's Which Deal With Opening of Service Manager (which is handle whole service database ) and then Opening OF particular Service.
    Code:
    SC_HANDLE OpenSCManager(  LPCTSTR lpMachineName, LPCTSTR lpDatabaseName, DWORD dwDesiredAccess);
    
    Here, if you want to access the local machine service database pass NULL in first two argument of openSCManager API to notify windows that we want to open local database of services.

    For accessing the remote machine services database, pass the target computer name must be prefixed by "\\".

    Important Note: You should have ADMIN Access to Operate SCManger other Wise you can only enumerate the Services but you can't alter them
    Code:
    SC_HANDLE OpenService(
      SC_HANDLE hSCManager,
      LPCTSTR lpServiceName,
      DWORD dwDesiredAccess
    );
    
    Here, the first Parameter is handle, that is Supplied by successful call Of OpenSCManager() API

    Second the Name OF SERVICE(Service name),which you want to Open

    Note: basically there are two type name One Display Name which we see when we Operate the Service Manager take look at next snapshot to get clear look.

    And third parameter is Some access flag for accessing services
    And Service name you got when you enumerate the service or you can see the properties of particular service get it real name, path etc look at next Screenshot for better understanding of this.

    I think you got the clear view of what are Service Name and Display name I according to Services Theory. :d

    Now this is the code for Enumerating all the services of local system, I will explain using à symbol in given code
    Code:
    void CServiceMgrDlg::UpDateListCtrl()
    {
    	///
    	//delete all item in listctrl
    	this->m_lstServices.DeleteAllItems();
    	SC_HANDLE ScManager;-> Handle to service
    
    	ENUM_SERVICE_STATUS EnService[512];
    
    	DWORD   cbBufSize=512*sizeof(ENUM_SERVICE_STATUS);
    
    	// size of status buffer
    
    	DWORD lpServicesReturned;
    
    	DWORD   pcbBytesNeeded;           // buffer size needed
    
    	DWORD   lpResumeHandle=0;           // next entry
    
    	CString str,csTemp;
    
    ->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 databse or not
    Code:
    if(ScManager==NULL)
    {
    	MessageBox("Error Opening Service Mgr");
    	return;
    }
    
    * Now call the EnumServicesstatus api call to enum all the service present in the computer
    * Also check that we are successful in retrieving the services or not
    * First Parameter is the handle return from successful call of OpenScManger
    * Second parameter indicate ,that we need only WIN32 based services
    * Third parameter return all the service whether it’s running or stop
    * Fourth parameter is a buffer of ENUM_SERVICE_STATUS in which all the services name will be return
    * Fifth parameter is buffer size of fourth parameter
    * Sixth parameter return with total byte of memory need to retrieve all the services
    * Seventh parameter return with total number of service return
    * And eight parameter indicate Pointer to a variable that, on input, specifies the starting point of enumeration. You must set this value to zero the first time this function is called. On output, this value is zero if the function succeeds. However, if the function returns zero and the GetLastError function returns ERROR_MORE_DATA, this value is used to indicate the next service entry to be read when the function is called to retrieve the additional data.

    Code:
    if(::EnumServicesStatus(ScManager,SERVICE_WIN32,SERVICE_STATE_ALL,EnService,cbBufSize,&pcbBytesNeeded,&lpServicesReturned,&lpResumeHandle )==0)
    {
    	MessageBox("Error Querrying Service Mgr");
    	return;
    }
    -> now check the state of each service
    Code:
    for(int i=0;i<int(lpServicesReturned);i++)
    {
    	csTemp.Format("%d",i+1);
    
    	this->m_lstServices.InsertItem(i,csTemp);
    
    	this->m_lstServices.SetItemText(i,1,EnService[i].lpServiceName); 
    
    	this->m_lstServices.SetItemText(i,2,EnService[i].lpDisplayName);
    
    ->the ENUM_SERVICE_STATUS third parameter contain the status of each service
    Code:
    switch(EnService[i].ServiceStatus.dwCurrentState)
    {
    case SERVICE_PAUSED:
    	this->m_lstServices.SetItemText(i,3,"paused");         
    	break; // The service is paused.
    case SERVICE_RUNNING:
    	this->m_lstServices.SetItemText(i,3,"running");         
    	break;// The service is running.
    case SERVICE_STOPPED :
    	this->m_lstServices.SetItemText(i,3,"stopped");         
    	break;// The service is stopped
    case SERVICE_START_PENDING :
    	this->m_lstServices.SetItemText(i,3,"starting");         
    	break;// The service is starting
    case SERVICE_STOP_PENDING :
    	this->m_lstServices.SetItemText(i,3,"stopping");         
    	break;// The service is stopped
    default:
    	this->m_lstServices.SetItemText(i,3,"unknown");         
    	break;// The service is running.
    }
    //block for start type
    {
    	SC_HANDLE ScService;     
    	QUERY_SERVICE_CONFIG ServiceConfig;
    	DWORD CbBufSize, pcbBytesNeeded;
    	CbBufSize=sizeof(QUERY_SERVICE_CONFIG);
    	CString SerState;
    
    ->Now opening each service to get it Startup type,eg wheather it Automatic or Manual or disable.
    Code:
    if((ScService=::OpenService(ScManager,EnService[i].lpServiceName,SERVICE_ALL_ACCESS))==NULL)
    {
    	::CloseHandle(ScManager);  
    	"Problem in opening service";
    }
    This api call will query the local database about the state of service.

    ->Here first parameter is hadle that we retrieve from successful call of OpenService

    -> second parameter is variable of QUERY_SERVICE_CONFIG which will receive the status
    Code:
    			 ::QueryServiceConfig(ScService,&ServiceConfig,CbBufSize,&pcbBytesNeeded);
    			switch(ServiceConfig.dwStartType)
    			{
    			case SERVICE_AUTO_START:this->m_lstServices.SetItemText(i,4,"Automatic"); break;
    			case SERVICE_DEMAND_START:this->m_lstServices.SetItemText(i,4,"Manual"); break;
    			case SERVICE_DISABLED :this->m_lstServices.SetItemText(i,4,"Disable"); break;
    			default:SerState=this->m_lstServices.SetItemText(i,4,"Unknown");
    			}
    		}
    	}
    	//str+=CString(EnService[i].lpServiceName);
    }
    
    Here I have taken Access as SC_MANAGER_ENUMERATE_SERVICE| GENERIC_READ as this access guarantee to enumerate Services for each user because we are only enumerating them

    Working of above function is like this

    1. First we open the scmanager with 'SC_MANAGER_ENUMERATE_SERVICE | GENERIC_READ' access Using the OpenSCManager Api
    2. the using the handle Given by above Successful Call of SCManager, Call Api EnumServicesStatus to enumerate the service present in local system.the important parameter in this function is struct Buff ENUM_SERVICE_STATUS ,which will bring back all the service Present in the computer.
    3. I think rest of code can be easily understood by a beginner.
    Now let understand how to Stop & Start the services

    To use Every Function of SCManger, you must get handle from the openSCManager to operate on Services.

    NOTE: You should have Admin right to perform RUN and Stop the services on local machine

    First Get Handle from OpenScManger like this

    SC_HANDLE ScManager,ScService;//Declaring the Some USeful Variable

    I think till now you have understand use of OpenSCmanager API
    Code:
    if((ScManager=::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS))==NULL)
    {
    	//preparing Error Variable
    	MessageBox("Error Opening System Manager");
    	return;
    }
    
    * Now get the handle OF service Using Api Open Service
    * Here first parameter is handle receive from successful call of OpenSCManager Api
    * Second parameter is the name of service to open
    * Third determine the access type to open service, here I have taken access as SERVICE_ALL_ACCESS .
    Code:
    if((ScService=::OpenService(ScManager,strServiceName,SERVICE_ALL_ACCESS))==NULL)
    {
    	//preparing Error Variable
    	MessageBox("Error Opening Service");
    	return;
    }
    Now you run you service using This Little Piece of Code.

    now using StartService api we can Run the previously stop service.

    here first parameter is handle which we receive from successful call of OpenService api

    the second parameter indicate any command line argument pass to service

    the third parameter according to MSDN

    Pointer to an array of pointers to null-terminated argument strings passed to a service. Driver services do not receive these arguments. If no arguments are passed to the service being started, this parameter can be NULL.
    Code:
    if(::StartService(ScService,0,NULL)==0)
    {
    	//preparing Error Variable
    	MessageBox("Error Starting Service");
    	return;
    }
    
    And You Can Stop Your service using this Little Piece Of Code. let me explain it to you
    -> First parameter is common as of above
    -> Second parameter specifies the requested control code
    -> Third parameter according to MSDN

    Pointer to a SERVICE_STATUS structure that receives the latest service status information. The information returned reflects the most recent status that the service reported to the service control manager.
    Code:
    if(::ControlService(ScService,SERVICE_CONTROL_STOP,&stt)==0)
    {
    	//preparing Error Variable
    	MessageBox("Error: Unable to Stop Service");
    	return;
    }
    
    And For Restarting there is no direct Api so you have to play the following trick for restarting the service “ First Stop the service And then run the service again “: d.

    Now Most important and Dangerous One (Deleting the service)

    Caution: please use this code with utmost care, because once it delete the service, this action can't be rollback. Unless you know how to install that service again

    Note: You need Admin right to perform this Action otherwise the action failed

    Here the Little Piece of code same way get the handle of both SCManager and Service

    SC_HANDLE ScManager,ScService;//Declaring the Some Useful Variable
    Code:
    if((ScManager=::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS))==NULL)
    {
    	//preparing Error Variable
    	MessageBox("Error Opening System Manager");
    	return;
    }
    if((ScService=::OpenService(ScManager,strServiceName,SERVICE_ALL_ACCESS))==NULL)
    {
    	//preparing Error Variable
    	MessageBox("Error Opening Service");
    	return;
    }
    
    ->for deleting the service there is very simple api named

    deleteService and only parameter it take is the handle of particular service
    Code:
    if(::DeleteService(ScService)==0)
    {
    	//preparing Error Variable
    	MessageBox("Error Deleting Service");
    	return;
    }
    else
    {
    	MessageBox("Service Marked For Deletion\nDeleted After Computer Restart");
    }
    The service after deletion was marked by SCmanger for Deletion and it get deleted after the computer is rebooted.

    I think I have explain each and very line of code, if you still face problem you can mail me in this regards

    GoodBye
     

    Attached Files:

  2. parvez.yu

    parvez.yu New Member

    Joined:
    Feb 14, 2008
    Messages:
    100
    Likes Received:
    0
    Trophy Points:
    0
    lengthy explanation
     
  3. chomchom

    chomchom New Member

    Joined:
    Jul 3, 2009
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
  4. rajeev_rsd

    rajeev_rsd New Member

    Joined:
    Sep 8, 2009
    Messages:
    4
    Likes Received:
    0
    Trophy Points:
    0
    One Beginner Question:

    As the Code above is written using Win32 API, is it compatible with all Windows Versions (like XP, VISTA, 7 both x86 and x64 editions)?

    By the way, lengthy but perfect explanation.

    - Rajeev
     
  5. naimish

    naimish New Member

    Joined:
    Jun 29, 2009
    Messages:
    1,043
    Likes Received:
    18
    Trophy Points:
    0
    Occupation:
    Software Engineer
    Location:
    On Earth
    Yes 100.00%
    NO 0%
    Some
    What 9.09%

    Total 109.09% ?????
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice