Thursday, 12 September 2013

Windows Service starting/stopping another service

Windows Service starting/stopping another service

I have a slight problem with a service I have written in C++. The service
itself functions correctly and is running under the SYSTEM account. During
one point of execution, I have to start or stop another service. This,
however, is not working. The call to OpenService() returns error code 5,
which is "Access denied".
To give a little bit more detail: I have to start an own time provider
service that tries to open port 123 on a network adapter, and this port is
often already opened by the win32time Service from Windows. What I try to
do is to give the user the option to automatically stop this service when
my service is starting, and starting it again when it stops.
This service can only be accessed with elevated user privileges on systems
that are UAC-capable, I know that, but I always thought that the SYSTEM
account would be able to perform this action by default, but apparently I
am wrong.
Is it possible somehow to elevate my service (maybe by adapting the
privilege level in the manifest to 'requireAdministrator' or something
similar)? I haven't tried this yet to be honest, since I fear that the UAC
prompt will be stuck in session 0 or things the like. Or is there another
way to grant my service running under SYSTEM the privileges to control
another service's status?
Any suggestions are very much appreciates, thanks!
EDIT
Okay, here's the code, and I feel a little bit stupid now... I have
totally forgotten to check the API thoroughly, because I thought that the
last parameter of OpenService() can be zero to request all privileges by
default, but I have to pass SC_MANAGER_ALL_ACCESS. Sorry for bothering
everybody. I will try this tomorrow and close this question when I have
the results.
SC_HANDLE scm = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE) ;
if(nullptr == scm) {
/* Handle and return */
}
// I am missing SC_MANAGER_ALL_ACCESS here probably
SC_HANDLE svc = OpenService(scm, _T("w32time"), 0);
int lastError = GetLastError();
if(ERROR_SERVICE_DOES_NOT_EXIST == lastError) {
/* Handle and return */
}
if(start) {
if(0 != StartService(svc, 0, nullptr)) {
int lastError = GetLastError();
if(ERROR_SERVICE_ALREADY_RUNNING != lastError) {
/* Handle */
}
}
} else {
SERVICE_STATUS status;
QueryServiceStatus(svc, &status);
if(SERVICE_STOPPED != status.dwCurrentState) {
if(ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
do {
QueryServiceStatus(svc, &status);
} while(SERVICE_STOPPED != status.dwCurrentState);
} else {
/* Handle */
}
}
}
CloseHandle(svc);
CloseHandle(scm);

No comments:

Post a Comment