Recently one of the customers had a problem with deploying their Windows Services over Vista. The Service, upon startup, displays a tray icon on the system tray and can be used to interact with the user. While the Service works fine on Windows XP and Windows 2003, it does not work properly under Vista.

The following post explains what has changed in Vista, why we had to change it, and how it is going to impact applications. Finally i devote a section to discussing how developers wanting to write services interact with the user, make minor code changes and make their applications compatible with Vista.

Backgrounder

In Windows XP, Windows Server 2003, and earlier versions of the Windows operating system, all services run in the same session as the first user who logs on to the console. This session is called Session 0. Running services and user applications together in Session 0 poses a security risk because services can run at elevated privilege(Local System account for example) and therefore are targets for malicious agents who are looking for a means to elevate their own privilege level.

The Microsoft Windows Vista operating system mitigates this security risk by isolating services in Session 0 and making Session 0 non-interactive. In Windows Vista, only system processes and services run in Session 0. The first user logs on to Session 1, and subsequent users log on to subsequent sessions. This means that services never run in the same session as users' applications and are therefore protected from attacks that originate in application code.

Before I explain more in detail about the Session 0 isolation and verious application compatibility issues, let me quickly walk you through determining which session your application runs under (this applies to all versions of Windows prior to Vista).

1) Open Task Manager (Click Windows Key + r and type “taskmgr”)

2) Select the Process tab.

3) Go To View Menu.. Select Columns

4) In the dialog, click the checkbox for “Session ID” and click OK:

5) Focus on the Session IDs for various applications. Notice that Services and applications run under the same session.

Under Windows Vista, the user applications (Visual Studio, Explorer) are not running in Session 0. All services are running in Session 0. (If the display does not show all the services, enable the check-box “Show processes from all users” at the bottom of the display.)

Session 0 Isolation and UI

Session 0 isolation introduces a problem for Services that need to display UI to the user. Since the Service is now running in a different Session and Desktop, the UI would not be visible to the end user and hence the application would appear to hang. Windows Vista has a temporary mitigation for this. In the next section, you will see how Windows Vista notifies you to switch to the Session 0 desktop to respond to interaction from legacy Services.

As mentioned, this mitigation is only temporary. The recommended way of showing UI is CreateProcessAsUser function to create a process in the user's session.

When the system detects that a service running in Session 0 is trying to communicate with the user, it displays a dialog similar to the one shown below. The developer can now switch to a desktop in Session 0 to interact with the dialog. Otherwise the service would be waiting for input and appear to hang.

Displaying UI in the User's Session

As mentioned above, the recommended way of showing UI is to use the CreateProcessAsUser function to create a process in the user's session. Looking up in MSDN, CreateProcessAsUser has the following syntax...

BOOL CreateProcessAsUser( HANDLE hToken, LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );

The first parameter is a HANDLE to a token and is a primary token that identifies the user. The immediate question before us is "How do i get a token for the user?" Another function LogonUser can be used to obtain the token for a user. However, LogonUser requires that one pass the user id and password in plain text format :) which is certainly not desirable.

I suggest the following method to obtain a primary token that identifies a user.

1) Call OpenProcess with PROCESS_ALL_ACCESS and open a user process. If the call is successful, it returns a handle to the process.

2) Use the handle obtained above to make a call to OpenProcessToken and specify TOKEN_ASSIGN_PRIMARY and TOKEN_DUPLICATE as the desired access. If the call is successful, it returns a handle to the process token.

3) Use the token handle obtained in step 2 above, and call DuplicateTokenEx function and specify TOKEN_ASSIGN_PRIMARY and TOKEN_ALL_ACCESS as the access rights. Also specify token type as TokenPrimary. If the call succeeds, it returns you a handle to a token which can be used as a primary token.

4) Call CreateProcessAsUser function to create an application in the user's session.

Few clarifications on the sequence of operations to be performed.

1) Every process that is launched by a user has the user's token associated with the process. This is done so that a particular process can be mapped back to the user who launched it.

2) The OpenProcessToken only returns an impersonated token which cannot be used in functions that require a primary token.

3) Further to step 2 above, we need to convert the impersonated token into a primary token and thus we use the function DuplicateTokenEx to achieve the same goal.

4) Once we convert the impersonated token into a primary token, we can use it in all the functions that need a primary token.

5) Once we are done using the token, we have to close it by calling CloseHandle.

 

I think this answers the most perplexing question regaring Session 0 and UI communication in Vista. Please feel free to post your comments, feedback and any other tips that you might have and i shall post an update accordingly.

 

This posting is provided "AS IS" with no warranties, and confers no rights. The Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm