views:

190

answers:

1

I have a service monitor app that monitors the status of three other servers app - you know those kind of green, red status stuff, start, stop, etc.

The problem is that it shows the wrong state in Windows 7 even if the user is the administrator.

The start, stop buttons are disabled and the install button enabled, the status color is grey which is also wrong. The start button should be enabled with the service status showing green - the apps are running.

If the application is run with the setting "run as administrator" then it behaves normally.

The application is written in Delphi 7 and works perfectly in other versions of Windows. This line of code:

OpenSCManager(PChar(sMachine), Nil, SC_MANAGER_ALL_ACCESS);

always return 0 under Win7, causing the problem.

Any ideas and if possible, any workaround apart from "run as administrator".

+6  A: 

The service manager can be opened without requiring Administrator privileges if limited access is requested. This line of code:

ManagerHandle := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE,
  SC_MANAGER_ENUMERATE_SERVICE);

opens the database of active services with the service manager, even when used from a limited user account. The returned handle can then be used to call EnumServicesStatusEx() to get information about the running services.

Passing SC_MANAGER_ALL_ACCESS as the dwDesiredAccess parameter implies passing SC_MANAGER_CREATE_SERVICE, and as the documentation states:

Only processes with Administrator privileges are able to open a database handle that can be used by the CreateService function.

So if you limit your program to actions that can be performed by standard users, then your code should run without changes on Windows 7. Everything else needs to be done either by the installer, or by a special program that runs elevated.

This is BTW no new requirement of Windows 7, your statement

The application is written in Delphi 7 and works perfectly in other versions of Windows.

shows only that you never properly tested the application on limited accounts in earlier versions of the OS. With Windows NT already (nearly 20 years ago) a limited user was not allowed to open the service manager with full access rights, so the code would fail there just the same.

mghie
Perfect answer!Never use the xxx_ALL_ACCESS flag for DesiredAccess parameter. Instead use only what is necessary. Furthermore, one shouldn't use GENERIC_xxxx rights here because their semantics may change from one Winversion to another (and they already have).
ChristianWimmer
Hey there - thanks for the answer and explanation.Will try your approach but, what about if I want also to start or stop the service - I mean, give the user the power to do that?
Ronaldo Junior
Starting and stopping a service may need more privileges than the current user has. In that case `OpenService(ManagerHandle, ServiceName, SERVICE_START or SERVICE_STOP)` will return 0 and `GetLastError()` will return the error code 5. That's the moment to require elevation, there are SO answers on how to do that using Delphi.
mghie