|< Windows Services Programming 1 | Main | Windows Services Programming 3 >| Site Index | Download |


 

 

 

MODULE DD1

WINDOWS SERVICES

Part 2: MORE STORY

 

 

 

What do we have in this Module?

  1. Multithreaded Services

  2. Services and Redirected Drives

  3. Redirected Drives on Windows NT and Windows 2000

  4. Redirected Drives on Windows XP

  5. Service Configuration Programs

  6. Service Installation, Removal, and Enumeration

  7. Service Configuration

  8. Configuring a Service Using SC Command

  9. Service Control Programs

  10. Service Startup

  11. Service Control Requests

  12. Controlling a Service Using SC Command

  13. Service User Accounts

  14. LocalService Account

  15. NetworkService Account

  16. LocalSystem Account

  17. More on LocalSystem Account

  18. Interactive Services

  19. Security Considerations for Interactive Services

  20. Interacting with the User from a Non-interactive Service

  21. Service Security and Access Rights

  22. Service Object

  23. Debugging a Service

  24. Window Stations

  25. Desktops

 

 

 

 

 

 

 

 

 

 

 

 

 

My Training Period:  xx hours. Before you begin, read some instruction here.

 

The Win32 programming skills:

  • Able to understand the Windows services concepts.

  • Able to understand the Service Control Manager (SCM).

  • Able to use the Windows Task Manager and Services snap-in.

  • Able to understand the security aspects of Windows services.

Multithreaded Services

 

The service control manager (SCM) controls a service by sending service control events to the service's control handler routine. The service must respond to control events in a timely manner so that the SCM can keep track of the state of the service. Also, the state of the service must match the description of its state that the SCM receives. Due to this communication mechanism between a service and the SCM, you must be careful when using multiple threads in a service. When a service is instructed to stop by the SCM, it must wait for all the threads to exit before reporting to the SCM that the service is stopped. Otherwise, the SCM can become confused about the state of the service and might fail to shut down correctly.

The SCM needs to be notified that the service is responding to the stop control event and that progress is being made in stopping the service. The SCM will assume the service is making progress if the service responds (through SetServiceStatus()) within the time (wait hint) specified in the previous call to SetServiceStatus(), and the check point is updated to be greater than the checkpoint specified in the previous call to SetServiceStatus(). If the service reports to the SCM that the service has stopped before all threads have exited, it is possible that the SCM will interpret this as a contradiction. This might result in a state where the service cannot be stopped or restarted.

 

Services and Redirected Drives

 

A service should not directly access local or network resources through mapped drive letters. Additionally, a service should not use the Windows Networking Functions to manage mapped drive letters. A service (or any process running in a different security context) that must access a remote resource should use the Universal Naming Convention (UNC) name to access the resource.

Although the WNet functions may return successfully, the resulting behavior is not as intended. When the system establishes a redirected drive, it is stored on a per-user basis. Only the user is able to manage the redirected drive. The system keeps track of redirected drives based on the user's logon security identifier (SID). The logon SID is a unique identifier for the user's logon session. A single user can have multiple, simultaneous logon sessions on the system. If a service is configured to run under a user account, the system always creates a new logon session for the user, and starts the service in that new logon session. Therefore, a service cannot manage the drive mappings established within the user's other session(s).

 

Redirected Drives on Windows NT and Windows 2000

 

Drive letters are global to the system. All users on the system share drive letters A-Z. Users do not get their own sets of drive letters. This means a user can access the redirected drives of another user as long as they have proper security access. Attempting to redirect a drive letter that is already in use results in an error. Although redirected drives are global to all users, only the user who established the mapping can manage it. If a user attempts to remove or query information on a redirected drive established by a different user, the API fails. If a user attempts to enumerate the list of redirected drives, the only redirected drives in the list are those established by that user. Drives redirected by other users are not visible.

Windows Explorer can see all redirected drives because it calls the GetDriveType() function for each drive and displays an icon for each drive found. Windows Explorer creates an icon for redirected drives created by all users because drive letters are global to the system. However, the interactive user cannot use Windows Explorer to disconnect the drive, because the drive was created within a different logon session. If a service is running in the security context of the LocalSystem account establishes a drive mapping, only that service or another process running in the LocalSystem account can disconnect the drive. Note that all processes running in the LocalSystem account are running in the same logon session.

 

Redirected Drives on Windows XP

 

Drive letters are not global to the system. Each logon session receives its own set of drive letters A-Z. Therefore, redirected drives cannot be shared between processes running under different user accounts. Moreover, a service (or any process running within its own logon session) cannot access the drive letters established within a different logon session.

 

Service Configuration Programs

 

Programmers and system administrators use service configuration programs to modify or query the database of installed services. The database can also be accessed by using the registry functions. However, you should only use the SCM configuration functions, which ensure that the service is properly installed and configured. The SCM configuration functions require either a handle to an SCManager object or a handle to a service object. To obtain these handles, the service configuration program must:

 

  1. Use the OpenSCManager() function to obtain a handle to the SCM database on a specified machine.

  2. Use the OpenService() or CreateService() function to obtain a handle to the service object.

 

Service Installation, Removal, and Enumeration

 

A configuration program uses the CreateService() function to install a new service in the SCM database. This function specifies the name of the service and provides configuration information that is stored in the database. A configuration program uses the DeleteService() function to remove an installed service from the database. To obtain the service name, call the GetServiceKeyName() function. The service display name, used in the Services control panel applet, can be obtained by calling the GetServiceDisplayName() function. A service configuration program can use the EnumServicesStatus() function to enumerate all services and their statuses. It can also use the EnumDependentServices() function to enumerate which services are dependent on a specified service object.

 

Service Configuration

 

The system uses the configuration information to determine how to start the service. The configuration information also includes the service display name and its description. For example, for the DHCP service, you could use the display name "Dynamic Host Configuration Protocol Service" and the description "Provides internet addresses for computer on your network." To modify the configuration information for a service object, a configuration program uses the ChangeServiceConfig() or ChangeServiceConfig2() function. To retrieve the configuration information for a service object, the configuration program uses the QueryServiceConfig() or QueryServiceConfig2() function. To modify the security descriptor for either an SCManager object or a service object, a configuration program uses the SetServiceObjectSecurity() function. To retrieve a copy of the security descriptor, the configuration program uses the QueryServiceObjectSecurity() function.

Before you reconfigure a service object, you should use the LockServiceDatabase() function. This function tries to acquire a lock on the database and, if successful, prevents the SCM from starting a service while the database is being reconfigured. Failure to acquire a lock does not prevent a configuration program from successfully reconfiguring a service object. To release the lock on the database when the reconfiguration is complete, use the UnlockServiceDatabase() function. To determine whether the database is locked, use the QueryServiceLockStatus() function.

 

Configuring a Service Using SC Command

 

The Platform SDK contains a command-line utility, sc.exe, which can be used to query or modify the database of installed services. Its commands correspond to the functions provided by the SCM. The syntax is:

 

Parameters

sc ServerName [command] ServiceName

ServerName - Optional server name. Use the form \\ServerName.

 

Command:

  1. query

  2. config

  3. qc

  4. delete

  5. create

  6. GetDisplayName

  7. GetKeyName

  8. EnumDepend

 

ServiceName - The name of the service, as specified when it was installed.

 

Screenshot example:

 

 

Service Control Programs

 

A service control program starts and controls services. It performs the following actions:

  1. Starts a service or driver service, if the start type is SERVICE_DEMAND_START.

  2. Sends control requests to a running service.

  3. Queries the current status of a running service.

 

These actions require an open handle to the service object. To obtain the handle, the service control program must:

 

  1. Use the OpenSCManager() function to obtain a handle to the SCM database on a specified machine.

  2. Use the OpenService() or CreateService() function to obtain a handle to the service object.

 

Service Startup

 

To start a service or driver service, the service control program uses the StartService() function. The StartService() function fails if the database is locked. If this occurs, the service control program should wait a few seconds and call StartService() again. It can check the current lock status of the database by calling the QueryServiceLockStatus() function.

If the service control program is starting a service, it can use the StartService() function to specify an array of arguments to be passed to the service's ServiceMain() function. The StartService() function returns after a new thread has been created to execute the ServiceMain() function. The service control program can retrieve the status of the newly started service in a SERVICE_STATUS structure by calling the QueryServiceStatus() function. During initialization, the dwCurrentState member should be SERVICE_START_PENDING. The dwWaitHint member is a time interval, in milliseconds, that indicates how long the service control program should wait before calling QueryServiceStatus() again. When the initialization is complete, the service changes dwCurrentState to SERVICE_RUNNING. If service does not update its status within 80 seconds, plus the last wait hint, the service control manager determines that the service has stopped responding. The service control manager will log an event and stop the service. If the program is starting a driver service, StartService() returns after the device driver has completed its initialization.

 

Service Control Requests

 

To send control requests to a running service, a service control program uses the ControlService() function. This function specifies a control value that is passed to the HandlerEx() function of the specified service. This control value can be a user-defined code, or it can be one of the standard codes that enable the calling program to perform the following actions:

  1. Stop a service (SERVICE_CONTROL_STOP).

  2. Pause a service (SERVICE_CONTROL_PAUSE).

  3. Resume executing a paused service (SERVICE_CONTROL_CONTINUE).

  4. Retrieve updated status information from a service (SERVICE_CONTROL_INTERROGATE).

 

Each service specifies the control values that it will accept and process. To determine which of the standard control values are accepted by a service, use the QueryServiceStatus() function or specify the SERVICE_CONTROL_INTERROGATE control value in a call to the ControlService() function. The dwControlsAccepted member of the SERVICE_STATUS structure returned by these functions indicates whether the service can be stopped, paused, or resumed. All services accept the SERVICE_CONTROL_INTERROGATE control value. Take note that the QueryServiceStatus() function reports the most recent status for a specified service, but does not get an updated status from the service itself. Using the SERVICE_CONTROL_INTERROGATE control value in a call to ControlService() ensures that the status information returned is current.

 

Controlling a Service Using SC Command

 

A command-line utility, sc.exe also can be used to control a service. Its commands correspond to the functions provided by the SCM.

 

Service User Accounts (SUA)

 

Each service executes in the security context of a user account. The user name and password of an account are specified by the CreateService() function at the time the service is installed. The user name and password can be changed by using the ChangeServiceConfig() function. You can use the QueryServiceConfig() function to get the user name (but not the password) associated with a service object. When starting a service, the SCM logs on to the account associated with the service. If the log on is successful, the system produces an access token and attaches it to the new service process. This token identifies the service process in all subsequent interactions with securable objects (objects that have a security descriptor associated with them). For example, if the service tries to open a handle to a pipe, the system compares the service's access token to the pipe's security descriptor before granting access.

The SCM does not maintain the passwords of service user accounts. If a password is expired, the logon fails and the service fails to start. The system administrator who assigns accounts to services can create accounts with passwords that never expire. The administrator can also manage accounts with passwords that expire by using a service configuration program to periodically change the passwords. If a service needs to recognize another service before sharing its information, the second service can either use the same account as the first service, or it can run in an account belonging to an alias that is recognized by the first service. Services that need to run in a distributed manner across the network should run in domain-wide accounts. You can use the following special accounts instead of creating user accounts for the service:

  1. LocalService.

  2. NetworkService.

  3. LocalSystem.

 

LocalService Account

 

The LocalService account is a predefined local account. It has minimum privileges on the local computer and presents anonymous credentials on the network. The name of the account in all locales is NT AUTHORITY\LocalService. This account does not have a password. If you specify the LocalService account in a call to the CreateService() function, any password information you supply is ignored. The user SID is created from the SECURITY_LOCAL_SERVICE_RID value. The LocalService account has its own subkey under the HKEY_USERS registry key. Therefore, the HKEY_CURRENT_USER registry key is associated with the LocalService account. The LocalService account has the following privileges:

  1. SE_AUDIT_NAME

  2. SE_CHANGE_NOTIFY_NAME

  3. SE_UNDOCK_NAME

  4. Any privileges assigned to users and authenticated users

 

This account is not supported for Windows 2000 and Windows NT.

 

NetworkService Account

 

The NetworkService account is a predefined local account. It has minimum privileges on the local computer and acts as the computer on the network. The name of the account in all locales is NT AUTHORITY\NetworkService. This account does not have a password. If you specify the NetworkService account in a call to the CreateService() function, any password information you supply is ignored. A service that runs in the context of the NetworkService account presents the computer's credentials to remote servers. By default, the remote token contains SIDs for the Everyone and Authenticated Users groups. The user SID is created from the SECURITY_NETWORK_SERVICE_RID value. The NetworkService account has its own subkey under the HKEY_USERS registry key. Therefore, the HKEY_CURRENT_USER registry key is associated with the NetworkService account. The NetworkService account has the following privileges:

  1. SE_AUDIT_NAME

  2. SE_CHANGE_NOTIFY_NAME

  3. SE_UNDOCK_NAME

  4. Any privileges assigned to users and authenticated users.

 

Windows 2000 and Windows NT:  This account is not supported.

 

LocalSystem Account

 

The LocalSystem account is a predefined local account. It has extensive privileges on the local computer, and acts as the computer on the network. The name of the account in all locales is .\LocalSystem (in other words, the corresponding C/C++ string with the backslash escaped is ".\\LocalSystem"). The name, "LocalSystem" or "ComputerName/LocalSystem" can also be used. This account does not have a password. If you specify the LocalSystem account in a call to the CreateService() function, any password information you supply is ignored. A service that runs in the context of the LocalSystem account inherits the security context of the SCM. The user SID is created from the SECURITY_LOCAL_SYSTEM_RID value. The account is not associated with any logged-on user account. This has several implications:

  1. The registry key HKEY_CURRENT_USER is associated with the default user, not the current user. To access another user's profile, impersonate the user, and then access HKEY_CURRENT_USER.

  2. The service can open the registry key HKEY_LOCAL_MACHINE\SECURITY.

  3. The service presents the computer's credentials to remote servers.

 

Windows NT:  The service has limited access to network resources, such as shares and pipes, because it has no credentials and must connect using a null session. The following registry key contains the NullSessionPipes and NullSessionShares values, which are used to specify the pipes and shares to which null sessions may connect:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters

Alternatively, you could add the REG_DWORD value RestrictNullSessAccess to the key and set it to 0 to allow all null sessions to access all pipes and shares created on that machine. If the service opens a command window and runs a batch file, the user could hit CTRL+C to terminate the batch file and gain access to a command window with LocalSystem permissions. The LocalSystem account has the following privileges and it is more powerful than the Administrator (Administrators group) account.

  1. SE_ASSIGNPRIMARYTOKEN_NAME

  2. SE_AUDIT_NAME

  3. SE_BACKUP_NAME

  4. SE_CHANGE_NOTIFY_NAME

  5. SE_CREATE_PAGEFILE_NAME

  6. SE_CREATE_PERMANENT_NAME

  7. SE_CREATE_TOKEN_NAME

  8. SE_DEBUG_NAME

  9. SE_INC_BASE_PRIORITY_NAME

  10. SE_INCREASE_QUOTA_NAME

  11. SE_LOAD_DRIVER_NAME

  12. SE_LOCK_MEMORY_NAME

  13. SE_PROF_SINGLE_PROCESS_NAME

  14. SE_RESTORE_NAME

  15. SE_SECURITY_NAME

  16. SE_SHUTDOWN_NAME

  17. SE_SYSTEM_ENVIRONMENT_NAME

  18. SE_SYSTEM_PROFILE_NAME

  19. SE_SYSTEMTIME_NAME

  20. SE_TAKE_OWNERSHIP_NAME

  21. SE_TCB_NAME

  22. SE_UNDOCK_NAME

 

Most services do not need such a high privilege level. If your service does not need these privileges, and it is not an interactive service, consider using the LocalService account or the NetworkService account.

 

More on LocalSystem Account

 

One advantage of running under the LocalSystem account is that the service has complete unrestricted access to local resources. This is also the disadvantage of LocalSystem because a LocalSystem service can do things that would bring down the entire system. In particular, a service running as LocalSystem on a domain controller (DC) has unrestricted access to Active Directory. This means that bugs in the service, or security attacks on the service, can damage the system or, if the service is on a DC, damage the entire enterprise network.

For these reasons, domain administrators at sensitive installations will be cautious about allowing services to run as LocalSystem. In fact, they may have policies against it, especially on DCs. If your service must run as LocalSystem, the documentation for your service should justify to domain administrators the reasons for granting the service the right to run at elevated privileges. Services should never run as LocalSystem on a domain controller.

When a service runs under the LocalSystem account on a computer that is a domain member, the service has whatever network access is granted to the computer account, or to any groups of which the computer account is a member. Be aware that in Windows 2000, a domain computer account is a service principal, similar to a user account. This means that a computer account can be in a security group, and an ACE in a security descriptor can grant access to a computer account. Be aware that adding computer accounts to groups is not recommended for two reasons:

  1. Computer accounts are subject to deletion and re-creation if the computer leaves and then rejoins the domain.

  2. If you add a computer account to a group, all services running as LocalSystem on that computer are permitted the access rights of the group. This is because all LocalSystem services share the computer account of their host server. For this reason, it is particularly important that computer accounts not be made members of any domain administrator groups.

 

Computer accounts typically have few privileges and do not belong to groups. The default Access Control List (ACL) protection in Active Directory permits minimal access for computer accounts. Consequently, services running as LocalSystem, on computers other than DCs, have only minimal access to Active Directory.

If your service runs under LocalSystem, you must test your service on a member server to ensure that your service has sufficient rights to read/write to Active Directory. A domain controller should not be the only Windows 2000 computer on which you test your service. Be aware that a service running under LocalSystem on a Windows 2000 domain controller has complete access to Active Directory and that a member server runs in the context of the computer account which has substantially fewer rights.

 

Interactive Services

 

Each service has an associated window station and desktop. Only one window station, Winsta0 can be an interactive. Any desktops created on the interactive window station can display objects to the user and receive user input. Other desktops cannot display objects or receive user input. Processes started by the logged-on user are associated with the default desktop in the Winsta0 window station (Winsta0\default). The particular window station and desktop combination used by a service is determined by the account in which the service is running. If the service is running in the security context of the LocalSystem account and does not include the SERVICE_INTERACTIVE_PROCESS attribute, it uses the following window station and desktop: Service-0x0-3e7$\default. This window station is not interactive, so the service cannot display a user interface. In addition, processes created by the service cannot display a user interface.

If the service is running in the security context of a user account, the name of the window station is based on the user SID: Service-0xZ1-Z2$, where Z1 is the high part of the logon SID and Z2 is the low part of the logon SID. Because a SID is unique to the logon session, two services running in the same security context receive unique window stations. If the service is running in the context of the LocalSystem account and has the SERVICE_INTERACTIVE_PROCESS attribute, it is known as an interactive service. It can display a user interface and receive user input. 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 zero, 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.

 

Security Considerations for Interactive Services

 

Note that running interactive services under the LocalSystem context is a dangerous practice and should be avoided. If a service that is running on a multi-user system must interact with a user, the service should do so through a separate GUI application running within the context of the user session. This GUI application should be designed to communicate with the service through some method of interprocess communication, such as a named pipe. This is a client/server implementation.

The server process (the interactive service) then communicates with the appropriate client through interprocess communication to tell the client when to display the GUI. The client then communicates the results of the user interaction back to the service so that the service can take the appropriate actions. By using named pipes, the server can distinguish between multiple user processes by giving each pipe a unique name.

 

Interacting with the User from a Non-interactive Service

 

It is possible to display a message box from a service, even if it is not running in the LocalSystem account or not configured to run interactively. Simply call the MessageBox() function using MB_SERVICE_NOTIFICATION. Do not call MessageBox() during service initialization or from the HandlerEx() routine, unless you call it from a separate thread, so that you return to the SCM in a timely manner.

It is also possible to interact with the desktop from a non-interactive service by modifying the DACLs on the window station and desktop, or by impersonating the logged-on user and opening the interactive window station and desktop directly. This allows services to provide a user interface, while maintaining the security of applications running in the account of the logged-on user.

 

Service Security and Access Rights

 

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

 

Service Control Manager (SCM)

 

The system creates the security descriptor for the SCM. Note that unlike most other securable objects, the security descriptor for the SCM cannot be modified. The following access rights are granted.

 

Account

Access rights

Authenticated users

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

 

Table 2

 

Windows 2000 and earlier:  The following access rights are granted.

 

Account

Access rights

Everyone

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

 

Table 3

 

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. The following are the specific access rights for the SCM.

 

Access right

Description

SC_MANAGER_ALL_ACCESS

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

SC_MANAGER_CREATE_SERVICE

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

SC_MANAGER_CONNECT

Required to connect to the service control manager.

SC_MANAGER_ENUMERATE_SERVICE

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

SC_MANAGER_LOCK

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

SC_MANAGER_BOOT_CONFIG

Required to call the NotifyBootConfigStatus() function.

SC_MANAGER_QUERY_LOCK_STATUS

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

 

Table 4

 

The following are the generic access rights for the SCM.

 

Access right

Description

GENERIC_READ

Combines the following access types:

STANDARD_RIGHTS_READ

SC_MANAGER_ENUMERATE_SERVICE

SC_MANAGER_QUERY_LOCK_STATUS

GENERIC_WRITE

Combines the following access types:

STANDARD_RIGHTS_WRITE

SC_MANAGER_CREATE_SERVICE

SC_MANAGER_MODIFY_BOOT_CONFIG

GENERIC_EXECUTE

Combines the following access types:

STANDARD_RIGHTS_EXECUTE

SC_MANAGER_CONNECT

SC_MANAGER_LOCK

GENERIC_ALL

SC_MANAGER_ALL_ACCESS

 

Table 5

 

A process with the correct access rights can open a handle to the SCM that can be used in the OpenService(), EnumServicesStatus(), 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.

 

Service Object

 

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

Authenticated users,

LocalService account,

NetworkService account

  1. READ_CONTROL

  2. SERVICE_ENUMERATE_DEPENDENTS

  3. SERVICE_INTERROGATE

  4. SERVICE_QUERY_CONFIG

  5. SERVICE_QUERY_STATUS

  6. SERVICE_USER_DEFINED_CONTROL

LocalSystem account,

Power Users group

  1. READ_CONTROL

  2. SERVICE_ENUMERATE_DEPENDENTS

  3. SERVICE_INTERROGATE

  4. SERVICE_PAUSE_CONTINUE

  5. SERVICE_QUERY_CONFIG

  6. SERVICE_QUERY_STATUS

  7. SERVICE_START

  8. SERVICE_STOP

  9. SERVICE_USER_DEFINED_CONTROL

Administrators group, System Operators group

  1. DELETE

  2. READ_CONTROL

  3. SERVICE_ALL_ACCESS

  4. WRITE_DAC

  5. WRITE_OWNER

 

Table 6

 

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. 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.

 

Table 7

 

The following are the specific access rights for a service.

 

Access right

Description

SERVICE_ALL_ACCESS

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

SERVICE_CHANGE_CONFIG

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

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

SERVICE_INTERROGATE

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

SERVICE_PAUSE_CONTINUE

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

SERVICE_QUERY_CONFIG

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

SERVICE_QUERY_STATUS

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

SERVICE_START

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

SERVICE_STOP

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

SERVICE_USER_DEFINED_CONTROL

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

 

Table 8

 

The following are the generic access rights for a service.

 

Access right

Description

GENERIC_READ

Combines the following access types: STANDARD_RIGHTS_READ

SERVICE_QUERY_CONFIG

SERVICE_QUERY_STATUS

SERVICE_INTERROGATE

SERVICE_ENUMERATE_DEPENDENTS.

GENERIC_WRITE

Combines the following access types: STANDARD_RIGHTS_WRITE

SERVICE_CHANGE_CONFIG.

GENERIC_EXECUTE

Combines the following access types: STANDARD_RIGHTS_EXECUTE

SERVICE_START

SERVICE_STOP

SERVICE_PAUSE_CONTINUE

SERVICE_USER_DEFINED_CONTROL.

 

Table 9

 

Granting certain access rights to untrusted 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.

 

Debugging a Service

 

You can use any one of the following methods to debug your service.

  1. Use your debugger to debug the service while it is running. First, obtain the process identifier (PID) of the service process. After you have obtained the PID, attach to the running process. For syntax information, see the documentation included with your debugger.

  2. Call the DebugBreak() function to invoke the debugger for just-in-time debugging.

  3. Specify a debugger to use when starting a program. To do so, create a key called Image File Execution Options in the following registry location:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion

Create a subkey with the same name as your service (for example, MYSERVICE.EXE). To this subkey, add a value of type REG_SZ, named Debugger. Use the full path to the debugger as the string value. In the Services control panel applet, select your service, click Startup and check Allow Service to Interact with Desktop. Note that the service must be an interactive service, or else the debugger cannot run on the default desktop.

To debug the initialization code of an auto-start service, you will have to temporarily install and run the service as a demand-start service. At times, it may be necessary to run a service as a console application for debugging purposes. In this scenario, the StartServiceCtrlDispatcher() function will return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT. Therefore, be sure to structure your code such that service-specific code is not called when this error is returned.

 

Window Stations

 

A window station is a securable object that is associated with a process, and contains a clipboard, an atom table, and a set of desktop objects. The interactive window station, Winsta0, is the only window station that can display a user interface or receive user input. It is assigned to the logon session of the interactive user, and contains the keyboard, mouse, and display device. All other window stations are non-interactive, which means they cannot display a user interface or receive user input. Running services under a different account prevents them from accessing the interactive window station. In this Module we will not discuss windows station in detail.

 

Desktops

 

A desktop is a securable object contained within a window station. A desktop has a logical display surface and contains windows, menus, and hooks. A window station can have multiple desktops. The desktops of the interactive window station, Winsta0, can be made to display a user interface and receive user input, but only one of these desktops at a time is active. This active desktop, also known as the input desktop, is the one that is currently visible to the user and that receives user input. Applications can use the OpenInputDesktop() function to get a handle to the input desktop. Applications that have the necessary access can use the SwitchDesktop() function to specify a different input desktop.

A desktop is associated with a thread and can be used to create and manage windows. There are three common desktops: default, Winlogon, and screen-saver. The default desktop is created when the logged-on user starts a process. It is the active desktop, and it is used to interact with the user. If you press the CTRL+ALT+DEL key sequence, you are switched to the Winlogon desktop. Whenever the screen saver activates, you are automatically switched to the screen-saver desktop, which protects the processes on the default desktop from unauthorized users. Unsecured screen savers run on Winsta0\default. Note that messages can be sent only between processes on the same desktop. In addition, the hook procedure of a process running on a particular desktop can only receive messages intended for windows created in the same desktop. In this Module we will not discuss desktop in detail.

 

 

----------------------------------------End of Windows Services Part 1----------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

 

  1. Structure, enum, union and typedef story can be found C/C++ struct, enum, union & typedef.

  2. For Multibytes, Unicode characters and Localization please refer to Locale, wide characters & Unicode (Story) and Windows users & groups programming tutorials (Implementation).

  3. Windows data types are Windows data types.

  4. Microsoft Visual C++, online MSDN.

  5. Check the best selling C / C++ and Windows books at Amazon.com.

  6. Win32 programming with Unicode  code samples.

 

 

 

 

 

 

|< Windows Services Programming 1 | Main | Windows Services Programming 3 >| Site Index | Download |