Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Terminal Services Listening Port Utility in Managed C++

0.00/5 (No votes)
19 Dec 2004 1  
Utility allowing convenient modification of a Terminal Servers listening port from 3389 to something else.

ts_port_utility/ts_port_utility.gif

Illustration 1: Terminal Services Listening Port Utility GUI

Introduction

Terminal Services and Remote Desktop both use the RDP protocol and a default port of 3389. Remote Desktop included in Windows XP is a watered down version of Terminal Services, and as such, it only allows for a single user session at a time. In contrast, Terminal Services available in Windows Server 2000 and Windows Server 2003 can be used in two distinctive modes:

  • Remote Administration - allowing up to two administrative users to login;
  • Application Server Mode - allows n amount of users to process applications on the server.

The Terminal Services Configuration and Management utilities provided by Microsoft as MMC snap-ins do not provide any TCP listening port options. The only way to change a Terminal Server’s default port from 3389 is via the Windows registry.

The Terminal Services Listening Port Utility hopes to showcase a simple managed C++ application which allows convenient modification of a Terminal Servers listening port on supported platforms.

Supported platforms

  • Windows 2000 Server
  • Windows 2000 Advanced Server
  • Windows XP Professional
  • Windows Server 2003

    [Windows XP Home only ships with the RDP Client and is not supported.]

Background

Having multiple live Terminal Servers at my command, I started to search for means of making them less obvious over the networks. Changing the default Terminal Server port from 3389 to something else seemed like a good place to start. This, in effect, hides a Terminal Server and at least, in theory, should improve security. Sure, Terminal Servers can still be discovered over a network, but only if one was to probe each port physically for a TS response.

Code Outline

The Terminal Services Listening Port Utility retrieves the Terminal Server TCP port value for the default network interface from the registry. The user is presented with the ability to specify a new port value, and if the new value represents a valid port, then the user may store this new value into the Windows registry.

Registry Operations

Registry access is performed via the Microsoft::Win32::RegistryKey class which represents a key level node in the Windows registry. This class is a Registry Encapsulation and is straightforward to use.

MC++
// Obtain Terminal Services Port from registry
private: System::Void MainForm_Load(System::Object * sender, 
                                      System::EventArgs * e)
{
    // Highest port possible is 65534 which is 5 characters
    txtPortNumber->MaxLength = 5;

    regKey = Registry->LocalMachine->
        OpenSubKey("System\\CurrentControlSet\\Control" 
                   "\\Terminal Server\\WinStations\\RDP-Tcp", 
        true );

    if(regKey != 0)    
        txtPortNumber->Text = 
           regKey->GetValue("PortNumber")->ToString();
    else
    {
        MessageBox::Show("Terminal Server not found in Registry");
        btnSet->Enabled = false;
    }
}

// Write New Port to Registry
private: System::Void btnSet_Click(System::Object * sender, 
                                     System::EventArgs * e)
{
    if(!IsValidPort(txtPortNumber->Text))
        errorProvider->SetError(txtPortNumber, 
             "A Port must be >= 1 and <= 65534");
    else
    {
        errorProvider->SetError(txtPortNumber, "");

        if(regKey != 0)
        {
            // store as REG_DWORD
            regKey->SetValue("PortNumber", 
              __box(Convert::ToInt32(txtPortNumber->Text))); 
            MessageBox::Show(String::Format("Port saved as {0}", 
              txtPortNumber->Text), "Success", 
              MessageBoxButtons::OK, MessageBoxIcon::Information);
        }
    }
}

Validation Routines

The Terminal Services Listening Port Utility implements the following two validation algorithms to restrict input and reduce user errors:

MC++
// determine whether the string qualifies as a port, 
// a valid port is an integer in the range of 1-65534 
private : bool IsValidPort(System::String * txtPort) 
{ 
    // we already know txtPort is numeric 
    // bit slow I suppose
    Int32 iPort = Int32::Parse(txtPort); 
    if (iPort < 1 || iPort > 65534) 
        return false; 
    else 
        return true; 
}
 
// determine whether the keystroke is an integer of the range 0-9 
// used in relation with the KeyPress event and Handled Property 
private : bool IsValidInt(System::String * ch) 
{ 
    String * format = "0123456789"; 

    if(format->IndexOf(ch)>=0) 
        return true; 
    else
        return false; 
} 

private: System::Void txtPortNumber_KeyPress(System::Object *  sender,
    System::Windows::Forms::KeyPressEventArgs *  e)
{
    // Stops the character from being entered
    // into the control since it is non-integer.
    if(!IsValidInt(e->KeyChar.ToString()) )
        e->Handled = true;
}

Client Configuration

Don’t forget to configure your Terminal Services client or Remote Desktop client to connect to the new port instead of the default port 3389. Firewalls or other NAT related appliances may have to be reconfigured for either pass through or port forwarding of any new ports.

For example, to instruct the Remote Desktop client utility to connect using the new port, simply append a colon followed by the non-standard port number to the computer address field.

Image 2

Illustration 2: XP Remote Desktop Client using non standard port

Related Resources

History

  • 12/17/04: Original submission
  • 12/20/04: Updated resources

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here