Go4Expert

Go4Expert (http://www.go4expert.com/)
-   Win32 (http://www.go4expert.com/articles/win32-tutorials/)
-   -   My Project:Service Manager (http://www.go4expert.com/articles/my-projectservice-manager-t182/)

alok 27Sep2004 14:28

My Project:Service Manager
 
1 Attachment(s)
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: CPP

SC_HANDLE OpenSCManager(  LPCTSTR lpMachineName, LPCTSTR lpDatabaseName, DWORD dwDesiredAccess);

Quote:

Originally Posted by MSDN
The OpenSCManager function establishes a connection to the service control manager on the specified computer and opens the specified service control manager database

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: CPP

SC_HANDLE OpenService(
  SC_HANDLE hSCManager,
  LPCTSTR lpServiceName,
  DWORD dwDesiredAccess
);

Quote:

Originally Posted by MSDN
The OpenService function opens an existing service.

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
Quote:

Originally Posted by MSDN
Specifies the access to the service. Before granting the requested access, the system checks the access token of the calling process against the discretionary access-control list of the security descriptor associated with the service object.

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: cpp

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_ENU MERATE_SERVICE|GENERIC_READ);

check that whether we able to connect with local computer service databse or not
Code: CPP

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: CPP

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: CPP

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: CPP

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: CPP

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: CPP

::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: CPP

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: CPP

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: CPP

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: CPP

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: CPP

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: CPP

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

parvez.yu 6Mar2008 15:16

Re: My Project:Service Manager
 
lengthy explanation

chomchom 3Jul2009 13:30

Re: My Project:Service Manager
 
thank u

rajeev_rsd 15Sep2009 06:24

Re: My Project:Service Manager
 
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

naimish 15Sep2009 08:07

Re: My Project:Service Manager
 
Yes 100.00%
NO 0%
Some
What 9.09%

Total 109.09% ?????


All times are GMT +5.5. The time now is 17:39.