How to modify or query the RDP connection permissions for Terminal Services

Important This article contains information about how to modify the registry. Make sure that you back up the registry before you modify it. Make sure that you know how to restore the registry if a problem occurs. For more information about how to back up, restore, and modify the registry, click the following article number to view the article in the Microsoft Knowledge Base:
256986 Description of the Microsoft Windows registry

INTRODUCTION

The Microsoft Terminal Services configuration application lets you change the Remote Desktop Protocol-Transmission Control Protocol (RDP-TCP) connection permissions. These permissions determine which users can perform actions (connect, disconnect, logoff, query, and so on) against a Terminal Services session.

An application can programmatically change the RDP-TCP connection permissions through the Microsoft Windows registry. If you are running Windows Server 2003 or a later version of Windows Server, use the WMI provider Win32_TSPermissionsSetting class to programmatically change the RDP-TCP connection permissions. For these programmatic changes to take effect, you must restart the computer that is running Windows Terminal Server.

To view a sample WMI Script that uses the Win32_TSPermissionsSetting class for Windows Server 2003, click the following article number to view the article in the Microsoft Knowledge Base:
290720 How to add a user to Terminal Services RDP permissions by using WMI

More Information

Warning Serious problems might occur if you modify the registry incorrectly by using Registry Editor or by using another method. These problems might require that you reinstall the operating system. Microsoft cannot guarantee that these problems can be solved. Modify the registry at your own risk.

The security descriptor is stored in self-relative format in the registry. To obtain or modify the security descriptor, you must convert it to absolute format. After you modify the security descriptor, you must convert it back to self-relative format, and then resave the change.

The default security settings are stored in the DefaultSecurity registry value under the following key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations
If you modify the security settings, they are stored in the Security value under the following key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
If you modify the default security descriptor and the Security value does not exist under the RDP-Tcp key, you must create the value.

Sample code

The following code demonstrates how to modify the current RDP-TCP connection permissions. This code checks for a modified security descriptor under the RDP-Tcp key. If none is found, it opens the default security descriptor under the WinStations key. After you modify the descriptor, it is saved under the RDP-Tcp key.
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#define USER_ACCESS 0x1A1
#define GUEST_ACCESS 0x20
#define FULL_CONTROL 0xF03FF

void _tmain(void) {

BYTE buffer[4096];
BYTE acl[1024];
DWORD dwAcl = sizeof(acl);
BYTE sacl[1024];
DWORD dwSacl = sizeof(sacl);
BYTE sidOwner[1024];
DWORD dwSidOwner = sizeof(sidOwner);
BYTE sidGroup[1024];
DWORD dwSidGroup = sizeof(sidGroup);
DWORD dwSize = sizeof(buffer);
HKEY hKey = NULL;
LONG lResult;
BYTE AbsSD[4096];
BYTE AbsModifiedSD[4096];
DWORD dwAbsMod = sizeof(AbsModifiedSD);

// Open the rdp-tcp key
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("system\\currentcontrolset\\control")
TEXT("\\terminal server\\winstations\\rdp-tcp"),
0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKey);
if (lResult != ERROR_SUCCESS) {
_tprintf(TEXT("RegOpenKeyEx failed with error %u\n"), lResult);
return;
}

// Query the Security value
lResult = RegQueryValueEx(hKey, TEXT("Security"), NULL, NULL, buffer,
&dwSize);

// Close the rdp-tcp key
RegCloseKey(hKey);

if (lResult != ERROR_SUCCESS && lResult != ERROR_FILE_NOT_FOUND) {
_tprintf(TEXT("RegQueryValueEx failed with error %u\n"),
lResult);
return;
}

// If the value was not present, get the default security descriptor
if (lResult == ERROR_FILE_NOT_FOUND) {

// Open the WinStations key
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("system\\currentcontrolset\\control")
TEXT("\\terminal server\\winstations"),
0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKey);
if (lResult != ERROR_SUCCESS) {
_tprintf(TEXT("RegOpenKeyEx failed with error %u\n"),
lResult);
return;
}

// Query the DefaultSecurity value
lResult = RegQueryValueEx(hKey, TEXT("DefaultSecurity"), NULL,
NULL, buffer, &dwSize);

// Close the WinStations key
RegCloseKey(hKey);

if (lResult != ERROR_SUCCESS) {
_tprintf(TEXT("RegQueryValueEx failed with error %u\n"),
lResult);
return;
}
}

// Convert the self-relative security descriptor to the absolute form
dwSize = sizeof(AbsSD);
if (!MakeAbsoluteSD((PSECURITY_DESCRIPTOR) buffer, AbsSD, &dwSize,
(PACL) acl, &dwAcl, (PACL) sacl, &dwSacl, (PSID) sidOwner,
&dwSidOwner, (PSID) sidGroup, &dwSidGroup)) {
_tprintf(TEXT("MakeAbsoluteSD failed with error %u\n"),
GetLastError());
return;
}

//
// TODO: Your code to modify the dacl goes here
//
// CAUTION: Incorrectly modifying the DACL may prevent the
// system from operating properly. For added safety, be sure
// to back up the registry before you run your code.
//



// Convert the security descriptor back to the self-relative form
if (!MakeSelfRelativeSD(AbsSD, AbsModifiedSD, &dwAbsMod)){
_tprintf(TEXT("MakeSelfRelativeSD failed with error %u\n"),
GetLastError());
return;
}

// Open the rdp-tcp key
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("system\\currentcontrolset\\control")
TEXT("\\terminal server\\winstations\\rdp-tcp"),
0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKey);
if (lResult != ERROR_SUCCESS) {
_tprintf(TEXT("RegOpenKeyEx failed with error %u\n"), lResult);
return;
}

// Save the modified security value
lResult = RegSetValueEx(hKey, TEXT("Security"), 0, REG_BINARY,
AbsModifiedSD, dwAbsMod);
if (lResult != ERROR_SUCCESS){
_tprintf(TEXT("RegSetValueEx failed with %u\n"), lResult);
return;
}

// Close the rdp-tcp key
RegCloseKey(hKey);
}
Properties

Article ID: 259129 - Last Review: Feb 13, 2007 - Revision: 1

Feedback