Windows Services Programming 8

 

 

 

 

 

Interactive Services

 

Typically, services are console applications that are designed to run unattended without a graphical user interface (GUI). However, some services may require occasional interaction with a user. This page discusses the best ways to interact with the user from a service. Important:  Services cannot directly interact with a user as of Windows Vista. Therefore, the techniques mentioned in the section titled Using an Interactive Service should not be used in new code.

 

Interacting with a User from a Service Indirectly

 

You can use the following techniques to interact with the user from a service on all supported versions of Windows:

  1. Display a dialog box in the user's session using the WTSSendMessage() function.

  2. Create a separate hidden GUI application and use the CreateProcessAsUser() function to run the application within the context of the interactive user. Design the GUI application to communicate with the service through some method of interprocess communication (IPC), for example, named pipes. The service communicates with the GUI application to tell it when to display the GUI. The application communicates the results of the user interaction back to the service so that the service can take the appropriate action. Note that IPC can expose your service interfaces over the network unless you use an appropriate access control list (ACL). If this service runs on a multiuser system, add the application to the following key so that it is run in each session: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run. If the application uses named pipes for IPC, the server can distinguish between multiple user processes by giving each pipe a unique name based on the session ID.

 

The following technique is also available for Windows Server 2003, Windows XP, and Windows 2000:

 

 

Using an Interactive Service

 

By default, services use a non-interactive window station and cannot interact with the user. However, an interactive service can display a user interface and receive user input.

Caution:  Services running in an elevated security context, such as the LocalSystem account, should not create a window on the interactive desktop because any other application that is running on the interactive desktop can interact with this window. This exposes the service to any application that a logged-on user executes. Also, services that are running as LocalSystem should not access the interactive desktop by calling the OpenWindowStation() or GetThreadDesktop() function. To create an interactive service, do the following when calling the CreateService() function:

 

  1. Specify NULL for the lpServiceStartName parameter to run the service in the context of the LocalSystem account.
  2. Specify the SERVICE_INTERACTIVE_PROCESS flag.

 

To determine whether a service is running as an interactive service, call the GetProcessWindowStation() function to retrieve a handle to the window station, and the GetUserObjectInformation() function to test whether the window station has the WSF_VISIBLE attribute. However, note that the following registry key contains a value, NoInteractiveServices, that controls the effect of SERVICE_INTERACTIVE_PROCESS:

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows

 

The NoInteractiveServices value defaults to 0, which means that services with SERVICE_INTERACTIVE_PROCESS are allowed to run interactively. When NoInteractiveServices is set to a nonzero value, no service started thereafter is allowed to run interactively, regardless of whether it has SERVICE_INTERACTIVE_PROCESS. Important:  All services run in Terminal Services session 0. Therefore, if an interactive service displays a user interface, it is visible only to the user who connected to session 0. Because there is no way to guarantee that the interactive user is connected to session 0, do not configure a service to run as an interactive service under Terminal Services or on a system that supports fast user switching (fast user switching is implemented using Terminal Services).

 

Service Security and Access Rights

 

The Windows security model enables you to control access to the service control manager (SCM) and service objects.

 

Access Rights for the Service Control Manager

 

The following are the specific access rights for the SCM.

 

Access right

Description

SC_MANAGER_ALL_ACCESS (0xF003F)

Includes STANDARD_RIGHTS_REQUIRED, in addition to all access rights in this table.

SC_MANAGER_CREATE_SERVICE (0x0002)

Required to call the CreateService() function to create a service object and add it to the database.

SC_MANAGER_CONNECT (0x0001)

Required to connect to the service control manager.

SC_MANAGER_ENUMERATE_SERVICE (0x0004)

Required to call the EnumServicesStatusEx() function to list the services that are in the database.

SC_MANAGER_LOCK (0x0008)

Required to call the LockServiceDatabase() function to acquire a lock on the database.

SC_MANAGER_MODIFY_BOOT_CONFIG (0x0020)

Required to call the NotifyBootConfigStatus() function.

SC_MANAGER_QUERY_LOCK_STATUS (0x0010)

Required to call the QueryServiceLockStatus() function to retrieve the lock status information for the database.

 

The following are the generic access rights for the SCM.

 

Access right

Description

GENERIC_READ

STANDARD_RIGHTS_READ

SC_MANAGER_ENUMERATE_SERVICE

SC_MANAGER_QUERY_LOCK_STATUS

GENERIC_WRITE

STANDARD_RIGHTS_WRITE

SC_MANAGER_CREATE_SERVICE

SC_MANAGER_MODIFY_BOOT_CONFIG

GENERIC_EXECUTE

STANDARD_RIGHTS_EXECUTE

SC_MANAGER_CONNECT

SC_MANAGER_LOCK

GENERIC_ALL

SC_MANAGER_ALL_ACCESS

 

A process with the correct access rights can open a handle to the SCM that can be used in the OpenService(), EnumServicesStatusEx(), and QueryServiceLockStatus() functions. Only processes with Administrator privileges are able to open handles to the SCM that can be used by the CreateService() and LockServiceDatabase() functions. The system creates the security descriptor for the SCM. To get or set the security descriptor for the SCM, use the QueryServiceObjectSecurity() and SetServiceObjectSecurity() functions with a handle to the SCManager object. Windows Server 2003 and Windows XP/2000:  Unlike most other securable objects, the security descriptor for the SCM cannot be modified. This behavior has changed as of Windows Server 2003 with Service Pack 1 (SP1). The following access rights are granted.

 

Account

Access rights

Remote authenticated users

SC_MANAGER_CONNECT

Local authenticated users (including LocalService and NetworkService)

SC_MANAGER_CONNECT

SC_MANAGER_ENUMERATE_SERVICE

SC_MANAGER_QUERY_LOCK_STATUS

STANDARD_RIGHTS_READ

LocalSystem

SC_MANAGER_CONNECT

SC_MANAGER_ENUMERATE_SERVICE

SC_MANAGER_MODIFY_BOOT_CONFIG

SC_MANAGER_QUERY_LOCK_STATUS

STANDARD_RIGHTS_READ

Administrators

SC_MANAGER_ALL_ACCESS

 

Notice that remote users authenticated over the network but not interactively logged on can connect to the SCM but not perform operations that require other access rights. To perform these operations, the user must be logged on interactively or the service must use one of the service accounts. For Windows Server 2003 and Windows XP the remote authenticated users are granted the SC_MANAGER_CONNECT, SC_MANAGER_ENUMERATE_SERVICE, SC_MANAGER_QUERY_LOCK_STATUS, and STANDARD_RIGHTS_READ access rights. These access rights are restricted as described in the previous table as of Windows Server 2003 with SP1. For Windows 2000, everyone is granted the SC_MANAGER_CONNECT, SC_MANAGER_ENUMERATE_SERVICE, SC_MANAGER_QUERY_LOCK_STATUS, and STANDARD_RIGHTS_READ access rights. When a process uses the OpenSCManager() function to open a handle to a database of installed services, it can request access rights. The system performs a security check against the security descriptor for the SCM before granting the requested access rights.

 

Access Rights for a Service

 

The following are the specific access rights for a service.

 

Access right

Description

SERVICE_ALL_ACCESS (0xF01FF)

Includes STANDARD_RIGHTS_REQUIRED in addition to all access rights in this table.

SERVICE_CHANGE_CONFIG (0x0002)

Required to call the ChangeServiceConfig() or ChangeServiceConfig2() function to change the service configuration. Because this grants the caller the right to change the executable file that the system runs, it should be granted only to administrators.

SERVICE_ENUMERATE_DEPENDENTS (0x0008)

Required to call the EnumDependentServices() function to enumerate all the services dependent on the service.

SERVICE_INTERROGATE (0x0080)

Required to call the ControlService() function to ask the service to report its status immediately.

SERVICE_PAUSE_CONTINUE (0x0040)

Required to call the ControlService() function to pause or continue the service.

SERVICE_QUERY_CONFIG (0x0001)

Required to call the QueryServiceConfig() and QueryServiceConfig2() functions to query the service configuration.

SERVICE_QUERY_STATUS (0x0004)

Required to call the QueryServiceStatusEx() function to ask the service control manager about the status of the service.

SERVICE_START (0x0010)

Required to call the StartService() function to start the service.

SERVICE_STOP (0x0020)

Required to call the ControlService() function to stop the service.

SERVICE_USER_DEFINED_CONTROL(0x0100)

Required to call the ControlService() function to specify a user-defined control code.

 

The following are the standard access rights for a service.

 

Access right

Description

ACCESS_SYSTEM_SECURITY

Required to call the QueryServiceObjectSecurity() or SetServiceObjectSecurity() function to access the SACL. The proper way to obtain this access is to enable the SE_SECURITY_NAME privilege in the caller's current access token, open the handle for ACCESS_SYSTEM_SECURITY access, and then disable the privilege.

DELETE

Required to call the DeleteService() function to delete the service.

READ_CONTROL

Required to call the QueryServiceObjectSecurity() function to query the security descriptor of the service object.

WRITE_DAC

Required to call the SetServiceObjectSecurity() function to modify the Dacl member of the service object's security descriptor.

WRITE_OWNER

Required to call the SetServiceObjectSecurity() function to modify the Owner and Group members of the service object's security descriptor.

 

The following are the generic access rights for a service.

 

Access right

Description

GENERIC_READ

STANDARD_RIGHTS_READ

SERVICE_QUERY_CONFIG

SERVICE_QUERY_STATUS

SERVICE_INTERROGATE

SERVICE_ENUMERATE_DEPENDENTS

GENERIC_WRITE

STANDARD_RIGHTS_WRITE

SERVICE_CHANGE_CONFIG

GENERIC_EXECUTE

STANDARD_RIGHTS_EXECUTE

SERVICE_START

SERVICE_STOP

SERVICE_PAUSE_CONTINUE

SERVICE_USER_DEFINED_CONTROL

 

The SCM creates a service object's security descriptor when the service is installed by the CreateService() function. The default security descriptor of a service object grants the following access.

 

Account

Access rights

Remote authenticated users

Not granted by default.

Windows Server 2003 with SP1:  SERVICE_USER_DEFINED_CONTROL

Windows Server 2003 and Windows XP:  The access rights for remote authenticated users are the same as for local authenticated users.

Local authenticated users (including LocalService and NetworkService)

READ_CONTROL

SERVICE_ENUMERATE_DEPENDENTS

SERVICE_INTERROGATE

SERVICE_QUERY_CONFIG

SERVICE_QUERY_STATUS

SERVICE_USER_DEFINED_CONTROL

LocalSystem

READ_CONTROL

SERVICE_ENUMERATE_DEPENDENTS

SERVICE_INTERROGATE

SERVICE_PAUSE_CONTINUE

SERVICE_QUERY_CONFIG

SERVICE_QUERY_STATUS

SERVICE_START

SERVICE_STOP

SERVICE_USER_DEFINED_CONTROL

Administrators

DELETE

READ_CONTROL

SERVICE_ALL_ACCESS

WRITE_DAC

WRITE_OWNER

 

To perform any operations, the user must be logged on interactively or the service must use one of the service accounts. To get or set the security descriptor for a service object, use the QueryServiceObjectSecurity() and SetServiceObjectSecurity() functions. When a process uses the OpenService() function, the system checks the requested access rights against the security descriptor for the service object. Granting certain access rights to un-trusted users (such as SERVICE_CHANGE_CONFIG or SERVICE_STOP) can allow them to interfere with the execution of your service, and possibly allow them to run applications under the LocalSystem account.

 

 

 

 

< Windows Services 7 | Win32 Programming | Windows Services Win32 Programming | Windows Services 9 >