Creating a Remote Desktop Plugin Using Delphi - Part 2

In part 1 of this series I set about creating a remote desktop plugin using Delphi. It didn’t do anything except initialize itself and display a few message boxes indicating its progress.  Not very useful.

In order for this whole thing to work the way I want it to, the plugin is going to have to interact with the user on the remote workstation.  This means displaying a form that will have to be on top of the remote desktop window.  I had some vague misgivings that remote desktop in full screen mode would be an “always on top” window that would interfere with the interaction that I need. So, as the next step in the process, I changed the plugin to create a form, make it an “always on top” window and display my status messages in a TMemo contained in the form.  Surprisingly enough this actually works quite well.

To make the Delphi form “always on top” I just created a method named SetTopmost and called if from the form’s OnShow event.

procedure TStatusForm.SetTopmost;

Since a useful plugin needs to be able to respond to events from the remote desktop client, I also implemented a VirtualChannelInitEvent handler in this version of the plugin.  This writes the event ID and remote server host name to the status form and destroys the status form when the remote desktop client terminates.

procedure  VirtualChannelInitEvent(pInitHandle: THandle;
               event: UINT;
               pData: Pointer;
               dataLength: UINT); stdcall;
  events: array [TChannelEvents] of String = (
    'V1 Connected',
    'Unknown 5',
    'Unknown 6',
    'Unknown 7',
    'Unknown 8',
    'Unknown 9',
    'Data Received',
    'Write Complete',
    'Write Cancelled'
  e: TChannelEvents;
  e := TChannelEvents(event);
  if ((e >= Low(events)) and (e <= High(events))) then
    StatusForm.SetStatus(Format('Unknown event id = %d', [event]));
  case e of
      StatusForm.SetStatus(Format('Server name = %s length = %d',

You can get the source code for the plugin as it stands so far here.

9 Responses to “Creating a Remote Desktop Plugin Using Delphi - Part 2”

  1. Peter Says:


    Thanks for the great series of articles. However this code does not work on Windows Server 2012 or Windows 8 (or Higher) as the server operating system. The status form shows and it shows the Initialized line but does not show “Connected” or the server name. This means the examples later in the series of articles do not work. Any clues as to what has gone wrong?


  2. lnsgod Says:

    You are quite right. I just found this out recently myself. RDP was completely rewritten in 2012. I had to take a really big wrench to this to get it working again. I had to move all client side logic to a separate worker thread to get things moving again.

  3. Peter Says:

    Hi Insgod

    Thanks for the info. Are you able to give me some more pointers as to where the thread would be created? Is it in the VirtualChannelEntry function or the VirtualChannelInitEvent or somewhere else?


  4. lnsgod Says:

    It actually got quite complicated. Easier to show you than try to explain it. I have put the source code for the entire plugin on my FTP site so you can look at it.

    I will leave it there for a few days and then delete it. So grab it quickly if you are interested.

  5. Peter Says:

    Hi Insgod

    Thanks for the files. It’s going to take me a bit to get my head around it but that is what weekends are for.

    Thanks again

  6. Stranger Says:

    Hi guys. I ran into this problem too (windows server 2012/2016). Please can you help with 2016 version sources. Thanks in advanced.

  7. lnsgod Says:

    I have updated the archive attached to this thread to contain the latest sources.

  8. Stranger Says:

    Hi. Thank you so much for your quick reply, you helped me a lot.
    I’ve tested your source code all day but my problem with opening the channel still persists.
    I have a problem when trying to open the channel from an outside network to the server(port forwarding) on a x64 operating system. When i try from the inside network the channel works perfectly fine,or from the outside network but on a x86 operating system. This behavior happens only on the windows server 2012/2016 x64.
    Maybe you observed some of this behavior.
    When the mstsc starts on localhost i receive the 0 event(initialize) , and then the 1 event for connected and the channel is opened.
    On the outside network only the initialize event is received.

    If i try to use WTSVirtualChannelOpen from the outside network the connection freezes and i have to force close the remote connection.

    If you have any ideas i would be very gratefull because i can’t seem to find any information anywhere. Thank you in andvance.

  9. lnsgod Says:

    This is the sort of thing I ran into before I changed the implementation to use a worker thread rather than doing everything in the main thread. Once I changed to mutli-threading I had no further problems.

    Sorry I can’t be more help than that.

Leave a Reply