| | 0

Programmatically Determining Terminal Server Mode on Windows Server 2008

A question on the terminal services newsgroup brought this topic to my attention: how can be determined programmatically if a Windows Server 2008 system is a terminal server and whether it runs in application server or remote administration mode? With Windows Server 2008 “terminal server” is a role that can be installed with the GUI tool Server Manager. If the role “terminal server” is installed then the system runs in application server mode. If not, it runs in remote administration mode. It is as simple as that. RDP connections can, however, be disallowed or limited to clients with Network Level Authentication (NLA). This is configured in the system’s properties, accessible via:

SystemPropertiesAdvanced.exe -> Remote -> Remote Desktop

Now, how can these settings be queried programmatically?

Roles and features can be managed with the command line tool ServerManagerCmd.exe. Use the switch -query to get a listing of all roles and features and their current status (installed or not). Finding out how to query the Remote Desktop settings was a little harder. I used Process Monitor to spy on the registry activity of SystemPropertiesAdvanced.exe when settings were applied and found the location where the relevant settings are stored. Here is a list of the three modes that can be set in the GUI and their corresponding registry values:

Don’t allow connections to this computer

HKLM\System\CurrentControlSet\Control\Terminal Server\fDenyTSConnections = 1 HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\UserAuthentication = 0 HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\SecurityLayer = 1

Allow connections from computers running any version of Remote Desktop (less secure)

HKLM\System\CurrentControlSet\Control\Terminal Server\fDenyTSConnections = 0 HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\UserAuthentication = 0 HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\SecurityLayer = 1

Allow connections only from computers running Remote Desktop with Network Level Authentication (more secure)

HKLM\System\CurrentControlSet\Control\Terminal Server\fDenyTSConnections = 0 HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\UserAuthentication = 1 HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\SecurityLayer = 1

Wrapping it all up

I wrote a batch script that uses the techniques I described above and outputs the mode the terminal services on the local machine run in. The script was developed and tested on the June CTP release of Windows Server 2008. Feel free to use it in your own environment.

@echo off

::
:: QueryTSMode.cmd
::
:: Author: Helge Klein
::
:: Version: 1.0
::
:: Date: 2007-09-08
::
:: Description:
::
:: Query whether terminal services are installed and in which mode they operate.
::

setlocal

::
:: Determine whether the role “terminal server” is installed
::
echo.
servermanagercmd -query | find /i “[X] Terminal Server [TS-Terminal-Server]” 1>nul
if %ERRORLEVEL%==0 (
echo The role “Terminal Server” is installed. The system operates in application server mode
) else (
echo The role “Terminal Server” is not installed. The system operates in remote administration mode
)
echo.

::
:: Determine terminal server connection configuration
::
call :RegReadValue HKLM “System\CurrentControlSet\Control\Terminal Server” FDENYTSCONNECTIONS fDenyTSConnections
call :RegReadValue HKLM “System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp” USERAUTHENTICATION UserAuthentication
call :RegReadValue HKLM “System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp” SECURITYLAYER SecurityLayer

if %FDENYTSCONNECTIONS%==1 (
echo Connections to this computer are not allowed
exit /b
)

if %USERAUTHENTICATION%==0×0 (
echo Connections are allowed from computers running any version of Remote Desktop
) else (
echo Connections are allowed only from computers running Remote Desktop with Network Level Authentication
)

goto :eof

::
:: Subroutines
::

:RegReadValue

set RegReadValueName=%~4
if defined RegReadValueName (
:: Read a named value
set RegReadValueCmd=/v “%RegReadValueName%”
) else (
:: Read the default value
set RegReadValueCmd=/ve
)

for /f “usebackq tokens=*” %%i in (`reg query “%~1\%~2″ %RegReadValueCmd% ^| find /i /v “%~1\%~2″ ^| find /i “%RegReadValueName%”`) do @set RegReadValueTemp=%%i
for /f “tokens=1,*” %%i in (”%RegReadValueTemp:*REG_=%”) do @set %3=%%j

set RegReadValueName=
set RegReadValueCmd=
set RegReadValueTemp=

goto :eof