I have created my first Windows service following this instruction. I can start or stop my service from the Service panel in Manage-> My computer without problem.
The service account is "LocalSystem" so, I think, I'm ok with privileges.
Now I want to communicate with my service from another app, but first of all I want to stop or start my service.
Following this example I Write this code:
LPCWSTR szSvcName = _T("MyNewService");
// Get a handle to the SCM database.
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
printf("OpenSCManager failed (%d)\n", GetLastError());
// Get a handle to the service.
schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_CHANGE_CONFIG); // need change config access
if (schService == NULL)
printf("OpenService failed (%d)\n", GetLastError());
//OK until now
// Check the status in case the service is not stopped.
schService, // handle to service
SC_STATUS_PROCESS_INFO, // information level
(LPBYTE) &ssStatus, // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded ) ) // size needed if buffer is too small
//printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
str.Format(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError()); //ERROR 5: ERROR_ACCESS_DENIED
// Check if the service is already running. It would be possible
// to stop the service here, but for simplicity this example just returns.
if(ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
printf("Cannot start the service because it is already running\n");
BOOL success = ::ControlService(schService, SERVICE_CONTROL_STOP, &ss);
You seem to be a little bit confused about terms "privileges" and "access rights". You are quite right that the LocalSystem account is really a privileged one, at least for actions on the local computer. However, even a privileged user must know how to take advantage if her privileges (how things work).
When an application wants to work with an object (e.g. a service), it has to declare its intention to the Windows kernel (done via
OpenService in your code). The application identifies the object (e.g. by service name) and also informs the kernel what sorts of things it plans to do with it. These "sorts of things" are called "access rights" and the kenrel decides whether the application is privileged enough to obtain the access rights it is requesting. In your code, you are requesting all access rights (
SC_MANAGER_ALL_ACCESS) for the SC manager and an access right to change configuration of your service (
SERVICE_CHANGE_CONFIG). Then, you attempt to query status of your service, but you did not declare this intention to the kernel when requesting access to the service (the
OpenService call). That's why you get the "access denied" error.
Here is a list of access rights defined for services and SC manager(s): https://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx. The document also contains information about which access rights you need to perform which actions.
To open a service, you need only the
SC_MANAGER_CONNECT access right to its SC manager. To query service status, the
SERVICE-QUERY_STATUS access right is required. To stop the service, request the
So, the short version is: specify
SERVICE_STOP | SERVICE_QUERY_STATUS desired access mask when calling
OpenService, and optionally
SC_MANAGER_CONNECT in the